From c786b65727f42b4702e1f2f2b6908ffccf0c05c2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 22 Apr 2016 19:54:51 +0200 Subject: [PATCH] - allow the engine to run without sampler objects. This will create some overhead in the texture code, but that's still better than having to error out on those few systems where it may be an issue. --- src/gl/system/gl_interface.cpp | 9 +- src/gl/system/gl_interface.h | 3 +- src/gl/system/gl_wipe.cpp | 6 +- src/gl/textures/gl_material.cpp | 8 +- src/gl/textures/gl_material.h | 1 + src/gl/textures/gl_samplers.cpp | 156 +++++++++++++++++++++++++------- src/gl/textures/gl_samplers.h | 2 +- 7 files changed, 140 insertions(+), 45 deletions(-) diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 3fd718ff70..3fcb7ced63 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -128,14 +128,15 @@ void gl_LoadExtensions() gl.vendorstring = (char*)glGetString(GL_VENDOR); - if (gl.version < 3.3f && !CheckExtension("GL_ARB_sampler_objects")) - { - I_FatalError("'GL_ARB_sampler_objects' extension not found. Please update your graphics driver."); - } if (CheckExtension("GL_ARB_texture_compression")) gl.flags|=RFL_TEXTURE_COMPRESSION; if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags|=RFL_TEXTURE_COMPRESSION_S3TC; if (!Args->CheckParm("-gl3")) { + if (gl.version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) + { + gl.flags |= RFL_SAMPLER_OBJECTS; + } + // don't use GL 4.x features when running in GL 3 emulation mode. if (CheckExtension("GL_ARB_buffer_storage")) { diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index 6f2fb2bfce..6988f873e1 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -10,7 +10,8 @@ enum RenderFlags RFL_TEXTURE_COMPRESSION_S3TC=2, RFL_SHADER_STORAGE_BUFFER = 4, - RFL_BUFFER_STORAGE = 8 + RFL_BUFFER_STORAGE = 8, + RFL_SAMPLER_OBJECTS = 16 }; enum TexMode diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 232be87a1c..00fc002f37 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -149,8 +149,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) wipestartscreen = new FHardwareTexture(Width, Height, true); wipestartscreen->CreateTexture(NULL, Width, Height, 0, false, 0); - GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); - GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE); + GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); + GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE, -1); glFinish(); wipestartscreen->Bind(0, false, false); GLint readbuffer = 0; @@ -176,7 +176,7 @@ void OpenGLFrameBuffer::WipeEndScreen() { wipeendscreen = new FHardwareTexture(Width, Height, true); wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0); - GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); + GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); glFinish(); wipeendscreen->Bind(0, false, false); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f5c8f90b35..961a61c04d 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -89,6 +89,7 @@ FGLTexture::FGLTexture(FTexture * tx, bool expandpatches) bHasColorkey = false; bIsTransparent = -1; bExpandFlag = expandpatches; + lastSampler = 254; tex->gl_info.SystemTexture[expandpatches] = this; } @@ -278,7 +279,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (translation <= 0) translation = -translation; else translation = GLTranslationPalette::GetInternalTranslation(translation); - bool needmipmap = (clampmode <= CLAMP_XY); + bool needmipmap = (clampmode <= CLAMP_XY) || !(gl.flags & RFL_SAMPLER_OBJECTS); FHardwareTexture *hwtex = CreateHwTexture(); @@ -313,9 +314,10 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla } delete[] buffer; } - + if (!needmipmap) clampmode = CLAMP_XY_NOMIP; if (tex->bHasCanvas) static_cast(tex)->NeedUpdate(); - GLRenderer->mSamplerManager->Bind(texunit, clampmode); + if (lastSampler != clampmode) + lastSampler = GLRenderer->mSamplerManager->Bind(texunit, clampmode, lastSampler); return hwtex; } return NULL; diff --git a/src/gl/textures/gl_material.h b/src/gl/textures/gl_material.h index b8a71c7ce8..83069049ca 100644 --- a/src/gl/textures/gl_material.h +++ b/src/gl/textures/gl_material.h @@ -65,6 +65,7 @@ private: bool bHasColorkey; // only for hires bool bExpandFlag; + BYTE lastSampler; unsigned char * LoadHiresTexture(FTexture *hirescheck, int *width, int *height); diff --git a/src/gl/textures/gl_samplers.cpp b/src/gl/textures/gl_samplers.cpp index 3851d6c718..db0193c697 100644 --- a/src/gl/textures/gl_samplers.cpp +++ b/src/gl/textures/gl_samplers.cpp @@ -44,69 +44,159 @@ #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderer.h" #include "gl_samplers.h" +#include "gl_material.h" extern TexFilter_s TexFilter[]; FSamplerManager::FSamplerManager() { - glGenSamplers(7, mSamplers); - SetTextureFilterMode(); - glSamplerParameteri(mSamplers[5], GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glSamplerParameteri(mSamplers[5], GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glSamplerParameterf(mSamplers[5], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - glSamplerParameterf(mSamplers[4], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - glSamplerParameterf(mSamplers[6], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + if (gl.flags & RFL_SAMPLER_OBJECTS) + { + glGenSamplers(7, mSamplers); + SetTextureFilterMode(); + glSamplerParameteri(mSamplers[5], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glSamplerParameteri(mSamplers[5], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glSamplerParameterf(mSamplers[5], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + glSamplerParameterf(mSamplers[4], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + glSamplerParameterf(mSamplers[6], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - glSamplerParameteri(mSamplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[2], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[2], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } } FSamplerManager::~FSamplerManager() { - UnbindAll(); - glDeleteSamplers(7, mSamplers); + if (gl.flags & RFL_SAMPLER_OBJECTS) + { + UnbindAll(); + glDeleteSamplers(7, mSamplers); + } } void FSamplerManager::UnbindAll() { - for (int i = 0; i < FHardwareTexture::MAX_TEXTURES; i++) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - mLastBound[i] = 0; - glBindSampler(i, 0); + for (int i = 0; i < FHardwareTexture::MAX_TEXTURES; i++) + { + mLastBound[i] = 0; + glBindSampler(i, 0); + } } } -void FSamplerManager::Bind(int texunit, int num) +BYTE FSamplerManager::Bind(int texunit, int num, int lastval) { - unsigned int samp = mSamplers[num]; - //if (samp != mLastBound[texunit]) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - glBindSampler(texunit, samp); - mLastBound[texunit] = samp; + unsigned int samp = mSamplers[num]; + //if (samp != mLastBound[texunit]) + { + glBindSampler(texunit, samp); + mLastBound[texunit] = samp; + return 255; + } + } + else + { + glActiveTexture(GL_TEXTURE0 + texunit); + switch (num) + { + case CLAMP_NONE: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_X: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_Y: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_XY_NOMIP: + case CLAMP_XY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_NOFILTER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + break; + + case CLAMP_CAMTEX: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + break; + } + glActiveTexture(GL_TEXTURE0); + return num; } } void FSamplerManager::SetTextureFilterMode() { - UnbindAll(); - - for (int i = 0; i < 4; i++) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); - glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + UnbindAll(); + + for (int i = 0; i < 4; i++) + { + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + } + else + { + GLRenderer->FlushTextures(); } - glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); } diff --git a/src/gl/textures/gl_samplers.h b/src/gl/textures/gl_samplers.h index 26589b4ad1..daba65d454 100644 --- a/src/gl/textures/gl_samplers.h +++ b/src/gl/textures/gl_samplers.h @@ -17,7 +17,7 @@ public: FSamplerManager(); ~FSamplerManager(); - void Bind(int texunit, int num); + BYTE Bind(int texunit, int num, int lastval); void SetTextureFilterMode();