only delete VBOs when the VAO, which uses the VBO, is deleted(AMD driver

bug under windows). And only allow true fullscreen under supported
display resolutions, to enable prevention of DPI scaled opengl viewport
This commit is contained in:
Jupeyy 2017-10-23 18:02:18 +02:00
parent ada954ea4e
commit 37c5102928
4 changed files with 108 additions and 26 deletions

View file

@ -763,6 +763,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
glGenBuffers(1, &m_QuadDrawIndexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
unsigned int Indices[CCommandBuffer::MAX_VERTICES/4 * 6];
int Primq = 0;
@ -1011,7 +1012,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Render(const CCommandBuffer::SComm
glDrawArrays(GL_LINES, 0, pCommand->m_PrimCount*2);
break;
case CCommandBuffer::PRIMTYPE_QUADS:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
if (m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
}
glDrawElements(GL_TRIANGLES, pCommand->m_PrimCount*6, GL_UNSIGNED_INT, 0);
break;
default:
@ -1110,8 +1115,10 @@ void CCommandProcessorFragment_OpenGL3_3::DestroyTexture(int Slot)
void CCommandProcessorFragment_OpenGL3_3::DestroyVisualObjects(int Index)
{
SVisualObject& VisualObject = m_VisualObjects[Index];
if(VisualObject.m_VertArrayID != 0) glDeleteVertexArrays(1, &VisualObject.m_VertArrayID);
if(VisualObject.m_VertBufferID != 0) glDeleteBuffers(1, &VisualObject.m_VertBufferID);//this line should never be called
if (VisualObject.m_VertArrayID != 0) glDeleteVertexArrays(1, &VisualObject.m_VertArrayID);
// this is required, due to a driver bug for AMD under windows
if(VisualObject.m_VertBufferID != 0) glDeleteBuffers(1, &VisualObject.m_VertBufferID);
VisualObject.m_NumElements = 0;
VisualObject.m_IsTextured = false;
@ -1135,7 +1142,6 @@ void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesC
Primq+=4;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_COPY_READ_BUFFER, m_QuadDrawIndexBufferID);
GLuint NewIndexBufferID;
glGenBuffers(1, &NewIndexBufferID);
@ -1149,7 +1155,6 @@ void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesC
glDeleteBuffers(1, &m_QuadDrawIndexBufferID);
m_QuadDrawIndexBufferID = NewIndexBufferID;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
m_CurrentIndicesInBuffer = NewIndicesCount;
delete[] Indices;
@ -1191,7 +1196,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuf
pProgram->SetUniform(pProgram->m_LocJumpIndex, (int)pCommand->m_JumpIndex);
glBindVertexArray(VisualObject.m_VertArrayID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
if (VisualObject.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
VisualObject.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
}
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, pCommand->m_pIndicesOffset, pCommand->m_DrawNum);
}
@ -1219,7 +1228,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTileLine(const CComman
pProgram->SetUniformVec2(pProgram->m_LocDir, 1, (float*)&pCommand->m_Dir);
glBindVertexArray(VisualObject.m_VertArrayID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
if (VisualObject.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
VisualObject.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
}
glDrawElementsInstanced(GL_TRIANGLES, pCommand->m_IndexDrawNum, GL_UNSIGNED_INT, pCommand->m_pIndicesOffset, pCommand->m_DrawNum);
}
@ -1252,9 +1265,11 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderVertexArray(const CCommandBu
pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color);
glBindVertexArray(VisualObject.m_VertArrayID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
//for some reasons this function seems not to be in the coreprofile for quite some gpus
//glMultiDrawElements(GL_TRIANGLES, pCommand->m_pDrawCount, GL_UNSIGNED_INT, pCommand->m_pIndicesOffsets, pCommand->m_IndicesDrawNum);
if (VisualObject.m_LastIndexBufferBound != m_QuadDrawIndexBufferID)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferID);
VisualObject.m_LastIndexBufferBound = m_QuadDrawIndexBufferID;
}
for (int i = 0; i < pCommand->m_IndicesDrawNum; ++i)
{
glDrawElements(GL_TRIANGLES, pCommand->m_pDrawCount[i], GL_UNSIGNED_INT, pCommand->m_pIndicesOffsets[i]);
@ -1348,9 +1363,8 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateVertArray(const CCommandBuff
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//TODO: destroy the VBO here? it shouldn't be needed anymore
glDeleteBuffers(1, &VisualObject.m_VertBufferID);
VisualObject.m_VertBufferID = 0;
// due to a driver bug for AMD hardware (https://stackoverflow.com/questions/41520764/should-i-delete-vertex-buffer-object-after-binding-it-to-vertex-array-objects)
// we don't delete the VBO bound to the VAO
}
// ------------ CCommandProcessorFragment_SDL
@ -1371,6 +1385,11 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand)
glDepthMask(0);
}
void CCommandProcessorFragment_SDL::Cmd_Update_Viewport(const SCommand_Update_Viewport* pCommand)
{
glViewport(pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height);
}
void CCommandProcessorFragment_SDL::Cmd_Shutdown(const SCommand_Shutdown *pCommand)
{
SDL_GL_MakeCurrent(NULL, NULL);
@ -1445,6 +1464,7 @@ bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::SCommand *p
case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast<const CCommandBuffer::SCommand_VideoModes *>(pBaseCommand)); break;
case CMD_INIT: Cmd_Init(static_cast<const SCommand_Init *>(pBaseCommand)); break;
case CMD_SHUTDOWN: Cmd_Shutdown(static_cast<const SCommand_Shutdown *>(pBaseCommand)); break;
case CMD_UPDATE_VIEWPORT: Cmd_Update_Viewport(static_cast<const SCommand_Update_Viewport *>(pBaseCommand)); break;
default: return false;
}
@ -1484,7 +1504,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer)
// ------------ CGraphicsBackend_SDL_OpenGL
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight)
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int* pCurrentWidth, int* pCurrentHeight)
{
if(!SDL_WasInit(SDL_INIT_VIDEO))
{
@ -1634,7 +1654,30 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
*pWidth = *pDesktopWidth;
*pHeight = *pDesktopHeight;
#else
SdlFlags |= SDL_WINDOW_FULLSCREEN;
//when we are at fullscreen, we really shouldn't allow window sizes, that aren't supported by the driver
bool SupportedResolution = false;
SDL_DisplayMode mode;
int maxModes = SDL_GetNumDisplayModes(g_Config.m_GfxScreen),
numModes = 0;
for (int i = 0; i < maxModes; i++)
{
if (SDL_GetDisplayMode(g_Config.m_GfxScreen, i, &mode) < 0)
{
dbg_msg("gfx", "unable to get display mode: %s", SDL_GetError());
continue;
}
if (*pWidth == mode.w && *pHeight == mode.h)
{
SupportedResolution = true;
break;
}
}
if(SupportedResolution)
SdlFlags |= SDL_WINDOW_FULLSCREEN;
else
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
}
@ -1721,8 +1764,39 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
WaitForIdle();
}
*pCurrentWidth = *pWidth;
*pCurrentHeight = *pHeight;
SDL_ShowWindow(m_pWindow);
SetWindowScreen(g_Config.m_GfxScreen);
if (SetWindowScreen(g_Config.m_GfxScreen))
{
// query the current displaymode, when running in fullscreen
// this is required if DPI scaling is active
if (SdlFlags&SDL_WINDOW_FULLSCREEN)
{
SDL_DisplayMode CurrentDisplayMode;
SDL_GetCurrentDisplayMode(g_Config.m_GfxScreen, &CurrentDisplayMode);
*pCurrentWidth = CurrentDisplayMode.w;
*pCurrentHeight = CurrentDisplayMode.h;
// since the window is centered, calculate how much the viewport has to be fixed
//int XOverflow = (*pWidth > *pCurrentWidth ? (*pWidth - *pCurrentWidth) : 0);
//int YOverflow = (*pHeight > *pCurrentHeight ? (*pHeight - *pCurrentHeight) : 0);
//TODO: current problem is, that the opengl driver knows about the scaled display,
//so the viewport cannot be adjusted for resolutions, that are higher than allowed by the display driver
CCommandProcessorFragment_SDL::SCommand_Update_Viewport CmdSDL;
CmdSDL.m_X = 0;
CmdSDL.m_Y = 0;
CmdSDL.m_Width = CurrentDisplayMode.w;
CmdSDL.m_Height = CurrentDisplayMode.h;
CmdBuffer.AddCommand(CmdSDL);
RunBuffer(&CmdBuffer);
WaitForIdle();
}
}
// return
return 0;

View file

@ -124,7 +124,7 @@ class CGLSLQuadProgram;
class CGLSLTileProgram;
class CGLSLBorderTileProgram;
class CGLSLBorderTileLineProgram;
// takes care of opengl 3.2 related rendering
// takes care of opengl 3.3 related rendering
class CCommandProcessorFragment_OpenGL3_3
{
bool m_UseMultipleTextureUnits;
@ -141,7 +141,6 @@ class CCommandProcessorFragment_OpenGL3_3
volatile int *m_pTextureMemoryUsage;
CGLSLPrimitiveProgram* m_pPrimitiveProgram;
//CGLSLQuadProgram* m_QuadProgram;
CGLSLTileProgram* m_pTileProgram;
CGLSLTileProgram* m_pTileProgramTextured;
CGLSLBorderTileProgram* m_pBorderTileProgram;
@ -151,6 +150,7 @@ class CCommandProcessorFragment_OpenGL3_3
GLuint m_PrimitiveDrawVertexID;
GLuint m_PrimitiveDrawBufferID;
GLuint m_LastIndexBufferBound;
GLuint m_QuadDrawIndexBufferID;
unsigned int m_CurrentIndicesInBuffer;
@ -172,9 +172,10 @@ class CCommandProcessorFragment_OpenGL3_3
void AppendIndices(unsigned int NewIndicesCount);
struct SVisualObject{
SVisualObject() : m_VertArrayID(0), m_VertBufferID(0), m_NumElements(0), m_IsTextured(false) {}
SVisualObject() : m_VertArrayID(0), m_VertBufferID(0), m_LastIndexBufferBound(0), m_NumElements(0), m_IsTextured(false) {}
GLuint m_VertArrayID;
GLuint m_VertBufferID;
GLuint m_LastIndexBufferBound;
int m_NumElements; //vertices and texture coordinates
bool m_IsTextured;
};
@ -239,6 +240,7 @@ public:
enum
{
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_SDL,
CMD_UPDATE_VIEWPORT,
CMD_SHUTDOWN,
};
@ -249,6 +251,15 @@ public:
SDL_GLContext m_GLContext;
};
struct SCommand_Update_Viewport : public CCommandBuffer::SCommand
{
SCommand_Update_Viewport() : SCommand(CMD_UPDATE_VIEWPORT) {}
int m_X;
int m_Y;
int m_Width;
int m_Height;
};
struct SCommand_Shutdown : public CCommandBuffer::SCommand
{
SCommand_Shutdown() : SCommand(CMD_SHUTDOWN) {}
@ -256,6 +267,7 @@ public:
private:
void Cmd_Init(const SCommand_Init *pCommand);
void Cmd_Update_Viewport(const SCommand_Update_Viewport* pCommand);
void Cmd_Shutdown(const SCommand_Shutdown *pCommand);
void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand);
void Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand);
@ -292,7 +304,7 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
bool m_UseOpenGL3_3;
public:
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight);
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int* pCurrentWidth, int* pCurrentHeight);
virtual int Shutdown();
virtual int MemoryUsage() const;

View file

@ -1212,7 +1212,7 @@ int CGraphics_Threaded::IssueInit()
if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
if(g_Config.m_GfxResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
int r = m_pBackend->Init("DDNet Client", &g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight);
int r = m_pBackend->Init("DDNet Client", &g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight, &m_ScreenWidth, &m_ScreenHeight);
m_UseOpenGL3_3 = m_pBackend->IsOpenGL3_3();
return r;
}
@ -1286,10 +1286,6 @@ int CGraphics_Threaded::Init()
else
m_pVertices = m_aVerticesOld;
// fetch final resolution
m_ScreenWidth = g_Config.m_GfxScreenWidth;
m_ScreenHeight = g_Config.m_GfxScreenHeight;
// create command buffers
for(int i = 0; i < NUM_CMDBUFFERS; i++)
m_apCommandBuffers[i] = new CCommandBuffer(256*1024, 2*1024*1024);

View file

@ -429,7 +429,7 @@ public:
virtual ~IGraphicsBackend() {}
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) = 0;
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int* pCurrentWidth, int* pCurrentHeight) = 0;
virtual int Shutdown() = 0;
virtual int MemoryUsage() const = 0;