- merged gzdoom-gles2 and fixed some issues with pipeline size validation.
This commit is contained in:
parent
a8a5613675
commit
441cd0796f
116 changed files with 12502 additions and 80 deletions
433
src/common/rendering/gles/gles_renderbuffers.cpp
Normal file
433
src/common/rendering/gles/gles_renderbuffers.cpp
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
** Postprocessing framework
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "gles_system.h"
|
||||
#include "v_video.h"
|
||||
#include "printf.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "gles_renderer.h"
|
||||
#include "gles_renderbuffers.h"
|
||||
#include "gles_postprocessstate.h"
|
||||
#include "gles_shaderprogram.h"
|
||||
#include "gles_buffers.h"
|
||||
#include "templates.h"
|
||||
#include <random>
|
||||
|
||||
EXTERN_CVAR(Int, gl_debug_level)
|
||||
|
||||
namespace OpenGLESRenderer
|
||||
{
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Initialize render buffers and textures used in rendering passes
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FGLRenderBuffers::FGLRenderBuffers()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Free render buffer resources
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FGLRenderBuffers::~FGLRenderBuffers()
|
||||
{
|
||||
ClearScene();
|
||||
|
||||
DeleteTexture(mDitherTexture);
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::ClearScene()
|
||||
{
|
||||
DeleteFrameBuffer(mSceneFB);
|
||||
DeleteRenderBuffer(mSceneDepthStencilBuf);
|
||||
DeleteRenderBuffer(mSceneStencilBuf);
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::DeleteTexture(PPGLTexture& tex)
|
||||
{
|
||||
if (tex.handle != 0)
|
||||
glDeleteTextures(1, &tex.handle);
|
||||
tex.handle = 0;
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::DeleteRenderBuffer(PPGLRenderBuffer& buf)
|
||||
{
|
||||
if (buf.handle != 0)
|
||||
glDeleteRenderbuffers(1, &buf.handle);
|
||||
buf.handle = 0;
|
||||
}
|
||||
|
||||
void FGLRenderBuffers::DeleteFrameBuffer(PPGLFrameBuffer& fb)
|
||||
{
|
||||
if (fb.handle != 0)
|
||||
glDeleteFramebuffers(1, &fb.handle);
|
||||
fb.handle = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes sure all render buffers have sizes suitable for rending at the
|
||||
// specified resolution
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height);
|
||||
|
||||
GLint activeTex;
|
||||
GLint textureBinding;
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
||||
|
||||
if (width != mWidth || height != mHeight)
|
||||
CreatePipeline(width, height);
|
||||
|
||||
if (width != mWidth || height != mHeight )
|
||||
CreateScene(width, height);
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mSceneWidth = sceneWidth;
|
||||
mSceneHeight = sceneHeight;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureBinding);
|
||||
glActiveTexture(activeTex);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
if (FailedCreate)
|
||||
{
|
||||
ClearScene();
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mSceneWidth = 0;
|
||||
mSceneHeight = 0;
|
||||
I_FatalError("Unable to create render buffers.");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates the scene buffers
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::CreateScene(int width, int height)
|
||||
{
|
||||
ClearScene();
|
||||
if(gles.depthStencilAvailable)
|
||||
mSceneDepthStencilBuf = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
||||
else
|
||||
{
|
||||
mSceneDepthStencilBuf = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH_COMPONENT16, width, height);
|
||||
mSceneStencilBuf = CreateRenderBuffer("SceneStencil", GL_STENCIL_INDEX8, width, height);
|
||||
}
|
||||
mSceneFB= CreateFrameBuffer("SceneFB", mSceneTex, mSceneDepthStencilBuf, mSceneStencilBuf);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates the buffers needed for post processing steps
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::CreatePipeline(int width, int height)
|
||||
{
|
||||
mSceneTex = Create2DTexture("PipelineTexture", GL_RGBA, width, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates a 2D texture defaulting to linear filtering and clamp to edge
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPGLTexture FGLRenderBuffers::Create2DTexture(const char* name, GLuint format, int width, int height, const void* data)
|
||||
{
|
||||
PPGLTexture tex;
|
||||
tex.Width = width;
|
||||
tex.Height = height;
|
||||
glGenTextures(1, &tex.handle);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.handle);
|
||||
|
||||
GLenum dataformat = 0, datatype = 0;
|
||||
/*
|
||||
switch (format)
|
||||
{
|
||||
case GL_RGBA: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break;
|
||||
|
||||
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
|
||||
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
|
||||
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
|
||||
case GL_R16F: dataformat = GL_RED; datatype = GL_FLOAT; break;
|
||||
case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break;
|
||||
case GL_RG16F: dataformat = GL_RG; datatype = GL_FLOAT; break;
|
||||
case GL_RGB10_A2: dataformat = GL_RGBA; datatype = GL_UNSIGNED_INT_10_10_10_2; break;
|
||||
case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break;
|
||||
|
||||
case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX8_OES; datatype = GL_INT; break;
|
||||
case GL_DEPTH24_STENCIL8_OES: dataformat = GL_DEPTH_STENCIL_OES; datatype = GL_UNSIGNED_INT_24_8; break;
|
||||
default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture");
|
||||
}
|
||||
*/
|
||||
format = GL_RGBA;
|
||||
dataformat = GL_RGBA;
|
||||
datatype = GL_UNSIGNED_BYTE;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, dataformat, datatype, data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
return tex;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates a render buffer
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPGLRenderBuffer FGLRenderBuffers::CreateRenderBuffer(const char* name, GLuint format, int width, int height)
|
||||
{
|
||||
PPGLRenderBuffer buf;
|
||||
glGenRenderbuffers(1, &buf.handle);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, buf.handle);
|
||||
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
|
||||
return buf;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates a frame buffer
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer)
|
||||
{
|
||||
PPGLFrameBuffer fb;
|
||||
glGenFramebuffers(1, &fb.handle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.handle);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0);
|
||||
if (CheckFrameBufferCompleteness())
|
||||
ClearFrameBuffer(false, false);
|
||||
return fb;
|
||||
}
|
||||
|
||||
PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil)
|
||||
{
|
||||
PPGLFrameBuffer fb;
|
||||
glGenFramebuffers(1, &fb.handle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.handle);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle);
|
||||
if (CheckFrameBufferCompleteness())
|
||||
ClearFrameBuffer(true, true);
|
||||
return fb;
|
||||
}
|
||||
|
||||
PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLRenderBuffer colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil)
|
||||
{
|
||||
PPGLFrameBuffer fb;
|
||||
glGenFramebuffers(1, &fb.handle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.handle);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer.handle);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle);
|
||||
if (CheckFrameBufferCompleteness())
|
||||
ClearFrameBuffer(true, true);
|
||||
return fb;
|
||||
}
|
||||
|
||||
PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer0, PPGLTexture colorbuffer1, PPGLTexture colorbuffer2, PPGLTexture depthstencil, PPGLRenderBuffer stencil)
|
||||
{
|
||||
PPGLFrameBuffer fb;
|
||||
glGenFramebuffers(1, &fb.handle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.handle);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0.handle, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle);
|
||||
|
||||
if (CheckFrameBufferCompleteness())
|
||||
ClearFrameBuffer(true, true);
|
||||
return fb;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Verifies that the frame buffer setup is valid
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FGLRenderBuffers::CheckFrameBufferCompleteness()
|
||||
{
|
||||
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (result == GL_FRAMEBUFFER_COMPLETE)
|
||||
return true;
|
||||
|
||||
bool FailedCreate = true;
|
||||
|
||||
|
||||
FString error = "glCheckFramebufferStatus failed: ";
|
||||
switch (result)
|
||||
{
|
||||
default: error.AppendFormat("error code %d", (int)result); break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break;
|
||||
}
|
||||
Printf("%s\n", error.GetChars());
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Clear frame buffer to make sure it never contains uninitialized data
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::ClearFrameBuffer(bool stencil, bool depth)
|
||||
{
|
||||
GLboolean scissorEnabled;
|
||||
GLint stencilValue;
|
||||
GLfloat depthValue;
|
||||
glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled);
|
||||
glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencilValue);
|
||||
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthValue);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClearDepthf(0.0f);
|
||||
glClearStencil(0);
|
||||
GLenum flags = GL_COLOR_BUFFER_BIT;
|
||||
if (stencil)
|
||||
flags |= GL_STENCIL_BUFFER_BIT;
|
||||
if (depth)
|
||||
flags |= GL_DEPTH_BUFFER_BIT;
|
||||
glClear(flags);
|
||||
glClearStencil(stencilValue);
|
||||
glClearDepthf(depthValue);
|
||||
if (scissorEnabled)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
|
||||
void FGLRenderBuffers::BindDitherTexture(int texunit)
|
||||
{
|
||||
if (!mDitherTexture)
|
||||
{
|
||||
static const float data[64] =
|
||||
{
|
||||
.0078125, .2578125, .1328125, .3828125, .0234375, .2734375, .1484375, .3984375,
|
||||
.7578125, .5078125, .8828125, .6328125, .7734375, .5234375, .8984375, .6484375,
|
||||
.0703125, .3203125, .1953125, .4453125, .0859375, .3359375, .2109375, .4609375,
|
||||
.8203125, .5703125, .9453125, .6953125, .8359375, .5859375, .9609375, .7109375,
|
||||
.0390625, .2890625, .1640625, .4140625, .0546875, .3046875, .1796875, .4296875,
|
||||
.7890625, .5390625, .9140625, .6640625, .8046875, .5546875, .9296875, .6796875,
|
||||
.1015625, .3515625, .2265625, .4765625, .1171875, .3671875, .2421875, .4921875,
|
||||
.8515625, .6015625, .9765625, .7265625, .8671875, .6171875, .9921875, .7421875,
|
||||
};
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
mDitherTexture = Create2DTexture("DitherTexture", GL_RGBA, 8, 8, data);
|
||||
}
|
||||
mDitherTexture.Bind(1, GL_NEAREST, GL_REPEAT);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes the scene frame buffer active (multisample, depth, stecil, etc.)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::BindSceneFB(bool sceneData)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB.handle);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Binds the current scene/effect/hud texture to the specified texture unit
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::BindCurrentTexture(int index, int filter, int wrap)
|
||||
{
|
||||
mSceneTex.Bind(index, filter, wrap);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes the frame buffer for the current texture active
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::BindCurrentFB()
|
||||
{
|
||||
#ifndef NO_RENDER_BUFFER
|
||||
mSceneFB.Bind();
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes the screen frame buffer active
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FGLRenderBuffers::BindOutputFB()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Returns true if render buffers are supported and should be used
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FGLRenderBuffers::FailedCreate = false;
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace OpenGLRenderer
|
||||
Loading…
Add table
Add a link
Reference in a new issue