From c9cf91e8da9130a8a942abdecfe96221fb72c196 Mon Sep 17 00:00:00 2001 From: Logan McNaughton Date: Thu, 12 Apr 2018 09:15:45 -0600 Subject: [PATCH] Add support for ext_shader_framebuffer_fetch --- src/DepthBuffer.cpp | 37 ++-- src/DepthBuffer.h | 2 +- src/FrameBuffer.cpp | 2 +- src/Graphics/Context.cpp | 7 + src/Graphics/Context.h | 6 +- src/Graphics/ContextImpl.h | 1 + src/Graphics/OpenGLContext/GLFunctions.cpp | 6 + src/Graphics/OpenGLContext/GLFunctions.h | 6 + .../GLSL/glsl_CombinerProgramBuilder.cpp | 161 +++++++++++++----- .../OpenGLContext/GLSL/glsl_ShaderStorage.h | 2 +- .../OpenGLContext/opengl_CachedFunctions.cpp | 12 +- .../OpenGLContext/opengl_ContextImpl.cpp | 20 ++- .../OpenGLContext/opengl_ContextImpl.h | 2 + src/Graphics/OpenGLContext/opengl_GLInfo.cpp | 31 +++- src/Graphics/OpenGLContext/opengl_GLInfo.h | 1 + .../OpenGLContext/opengl_Parameters.cpp | 2 + src/Graphics/Parameters.h | 2 + 17 files changed, 224 insertions(+), 76 deletions(-) diff --git a/src/DepthBuffer.cpp b/src/DepthBuffer.cpp index 1d08b40a..f7317862 100644 --- a/src/DepthBuffer.cpp +++ b/src/DepthBuffer.cpp @@ -317,21 +317,34 @@ void DepthBuffer::activateDepthBufferTexture(FrameBuffer * _pBuffer) gfxContext.textureBarrier(); } -void DepthBuffer::bindDepthImageTexture() +void DepthBuffer::bindDepthImageTexture(ObjectHandle _fbo) { - if (!Context::ImageTextures) - return; + if (Context::ImageTextures) { + Context::BindImageTextureParameters bindParams; + bindParams.imageUnit = textureImageUnits::DepthZ; + bindParams.texture = m_pDepthImageZTexture->name; + bindParams.accessMode = textureImageAccessMode::READ_WRITE; + bindParams.textureFormat = gfxContext.getFramebufferTextureFormats().depthImageInternalFormat; + gfxContext.bindImageTexture(bindParams); - Context::BindImageTextureParameters bindParams; - bindParams.imageUnit = textureImageUnits::DepthZ; - bindParams.texture = m_pDepthImageZTexture->name; - bindParams.accessMode = textureImageAccessMode::READ_WRITE; - bindParams.textureFormat = gfxContext.getFramebufferTextureFormats().depthImageInternalFormat; - gfxContext.bindImageTexture(bindParams); + bindParams.imageUnit = textureImageUnits::DepthDeltaZ; + bindParams.texture = m_pDepthImageDeltaZTexture->name; + gfxContext.bindImageTexture(bindParams); + } else if (Context::FramebufferFetch) { + Context::FrameBufferRenderTarget targetParams; + targetParams.bufferHandle = _fbo; + targetParams.bufferTarget = bufferTarget::DRAW_FRAMEBUFFER; + targetParams.attachment = bufferAttachment::COLOR_ATTACHMENT1; + targetParams.textureHandle = m_pDepthImageZTexture->name; + targetParams.textureTarget = textureTarget::TEXTURE_2D; + gfxContext.addFrameBufferRenderTarget(targetParams); - bindParams.imageUnit = textureImageUnits::DepthDeltaZ; - bindParams.texture = m_pDepthImageDeltaZTexture->name; - gfxContext.bindImageTexture(bindParams); + targetParams.attachment = bufferAttachment::COLOR_ATTACHMENT2; + targetParams.textureHandle = m_pDepthImageDeltaZTexture->name; + gfxContext.addFrameBufferRenderTarget(targetParams); + + gfxContext.setDrawBuffers(3); + } } DepthBufferList::DepthBufferList() : m_pCurrent(nullptr), m_pzLUT(nullptr) diff --git a/src/DepthBuffer.h b/src/DepthBuffer.h index bc6b0922..4cfd56fb 100644 --- a/src/DepthBuffer.h +++ b/src/DepthBuffer.h @@ -20,7 +20,7 @@ struct DepthBuffer void setDepthAttachment(graphics::ObjectHandle _fbo, graphics::BufferTargetParam _target); void activateDepthBufferTexture(FrameBuffer * _pBuffer); - void bindDepthImageTexture(); + void bindDepthImageTexture(graphics::ObjectHandle _fbo); u32 m_address, m_width; u32 m_ulx, m_uly, m_lrx, m_lry; // Parameters of fillrect command. diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index b987d9ff..2a79a3a5 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -807,7 +807,7 @@ void FrameBufferList::attachDepthBuffer() pCurrent->m_pDepthBuffer = pDepthBuffer; pDepthBuffer->setDepthAttachment(pCurrent->m_FBO, bufferTarget::DRAW_FRAMEBUFFER); if (config.frameBufferEmulation.N64DepthCompare != 0) - pDepthBuffer->bindDepthImageTexture(); + pDepthBuffer->bindDepthImageTexture(pCurrent->m_FBO); } else pCurrent->m_pDepthBuffer = nullptr; } else diff --git a/src/Graphics/Context.cpp b/src/Graphics/Context.cpp index 759d079c..13f92e17 100644 --- a/src/Graphics/Context.cpp +++ b/src/Graphics/Context.cpp @@ -13,6 +13,7 @@ bool Context::ShaderProgramBinary = false; bool Context::ImageTextures = false; bool Context::IntegerTextures = false; bool Context::ClipControl = false; +bool Context::FramebufferFetch = false; Context::Context() {} @@ -34,6 +35,7 @@ void Context::init() ImageTextures = m_impl->isSupported(SpecialFeatures::ImageTextures); IntegerTextures = m_impl->isSupported(SpecialFeatures::IntegerTextures); ClipControl = m_impl->isSupported(SpecialFeatures::ClipControl); + FramebufferFetch = m_impl->isSupported(SpecialFeatures::FramebufferFetch); } void Context::destroy() @@ -214,6 +216,11 @@ bool Context::blitFramebuffers(const BlitFramebuffersParams & _params) return m_impl->blitFramebuffers(_params); } +void Context::setDrawBuffers(u32 _num) +{ + m_impl->setDrawBuffers(_num); +} + PixelReadBuffer * Context::createPixelReadBuffer(size_t _sizeInBytes) { return m_impl->createPixelReadBuffer(_sizeInBytes); diff --git a/src/Graphics/Context.h b/src/Graphics/Context.h index ba1729f6..a93207fd 100644 --- a/src/Graphics/Context.h +++ b/src/Graphics/Context.h @@ -23,7 +23,8 @@ namespace graphics { ShaderProgramBinary, ImageTextures, IntegerTextures, - ClipControl + ClipControl, + FramebufferFetch }; enum class ClampMode { @@ -202,6 +203,8 @@ namespace graphics { bool blitFramebuffers(const BlitFramebuffersParams & _params); + void setDrawBuffers(u32 _num); + /*---------------Pixelbuffer-------------*/ PixelReadBuffer * createPixelReadBuffer(size_t _sizeInBytes); @@ -281,6 +284,7 @@ namespace graphics { static bool ImageTextures; static bool IntegerTextures; static bool ClipControl; + static bool FramebufferFetch; private: std::unique_ptr m_impl; diff --git a/src/Graphics/ContextImpl.h b/src/Graphics/ContextImpl.h index f6ac650e..b3f43a70 100644 --- a/src/Graphics/ContextImpl.h +++ b/src/Graphics/ContextImpl.h @@ -46,6 +46,7 @@ namespace graphics { virtual ObjectHandle createRenderbuffer() = 0; virtual void initRenderbuffer(const Context::InitRenderbufferParams & _params) = 0; virtual bool blitFramebuffers(const Context::BlitFramebuffersParams & _params) = 0; + virtual void setDrawBuffers(u32 _num) = 0; virtual PixelReadBuffer * createPixelReadBuffer(size_t _sizeInBytes) = 0; virtual ColorBufferReader * createColorBufferReader(CachedTexture * _pTexture) = 0; virtual bool isCombinerProgramBuilderObsolete() = 0; diff --git a/src/Graphics/OpenGLContext/GLFunctions.cpp b/src/Graphics/OpenGLContext/GLFunctions.cpp index 4b4c6911..b1a38732 100644 --- a/src/Graphics/OpenGLContext/GLFunctions.cpp +++ b/src/Graphics/OpenGLContext/GLFunctions.cpp @@ -192,6 +192,9 @@ PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC g_glDrawRangeElementsBaseVertex; PFNGLFLUSHMAPPEDBUFFERRANGEPROC g_glFlushMappedBufferRange; PFNGLTEXTUREBARRIERPROC g_glTextureBarrier; PFNGLTEXTUREBARRIERNVPROC g_glTextureBarrierNV; +PFNGLCLEARBUFFERFVPROC g_glClearBufferfv; +PFNGLENABLEIPROC g_glEnablei; +PFNGLDISABLEIPROC g_glDisablei; void initGLFunctions() { @@ -334,4 +337,7 @@ void initGLFunctions() GL_GET_PROC_ADR(PFNGLFLUSHMAPPEDBUFFERRANGEPROC, glFlushMappedBufferRange); GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERPROC, glTextureBarrier); GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERNVPROC, glTextureBarrierNV); + GL_GET_PROC_ADR(PFNGLCLEARBUFFERFVPROC, glClearBufferfv); + GL_GET_PROC_ADR(PFNGLENABLEIPROC, glEnablei); + GL_GET_PROC_ADR(PFNGLDISABLEIPROC, glDisablei); } diff --git a/src/Graphics/OpenGLContext/GLFunctions.h b/src/Graphics/OpenGLContext/GLFunctions.h index 3cc9b7d4..3b81df1d 100644 --- a/src/Graphics/OpenGLContext/GLFunctions.h +++ b/src/Graphics/OpenGLContext/GLFunctions.h @@ -216,6 +216,9 @@ extern PFNGLBLENDCOLORPROC g_glBlendColor; #define glFlushMappedBufferRange(...) CHECKED_GL_FUNCTION(g_glFlushMappedBufferRange, __VA_ARGS__) #define glTextureBarrier(...) CHECKED_GL_FUNCTION(g_glTextureBarrier, __VA_ARGS__) #define glTextureBarrierNV(...) CHECKED_GL_FUNCTION(g_glTextureBarrierNV, __VA_ARGS__) +#define glClearBufferfv(...) CHECKED_GL_FUNCTION(g_glClearBufferfv, __VA_ARGS__) +#define glEnablei(...) CHECKED_GL_FUNCTION(g_glEnablei, __VA_ARGS__) +#define glDisablei(...) CHECKED_GL_FUNCTION(g_glDisablei, __VA_ARGS__) extern PFNGLCREATESHADERPROC g_glCreateShader; extern PFNGLCOMPILESHADERPROC g_glCompileShader; @@ -312,6 +315,9 @@ extern PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC g_glDrawRangeElementsBaseVertex; extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC g_glFlushMappedBufferRange; extern PFNGLTEXTUREBARRIERPROC g_glTextureBarrier; extern PFNGLTEXTUREBARRIERNVPROC g_glTextureBarrierNV; +extern PFNGLCLEARBUFFERFVPROC g_glClearBufferfv; +extern PFNGLENABLEIPROC g_glEnablei; +extern PFNGLDISABLEIPROC g_glDisablei; void initGLFunctions(); diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index 6f2d1759..7bc36061 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -460,9 +460,11 @@ public: if (_glinfo.noPerspective) ss << "#extension GL_NV_shader_noperspective_interpolation : enable" << std::endl; if (config.frameBufferEmulation.N64DepthCompare != 0) { - if (_glinfo.fragment_interlockNV) + if (_glinfo.imageTextures && _glinfo.fragment_interlockNV) { ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl << "layout(pixel_interlock_ordered) in;" << std::endl; + } else if (_glinfo.ext_fetch) + ss << "#extension GL_EXT_shader_framebuffer_fetch : enable" << std::endl; } ss << "# define IN in" << std::endl << "# define OUT out" << std::endl @@ -472,18 +474,21 @@ public: std::stringstream ss; ss << "#version " << Utils::to_string(_glinfo.majorVersion) << Utils::to_string(_glinfo.minorVersion) << "0 core " << std::endl; if (config.frameBufferEmulation.N64DepthCompare != 0) { - if (_glinfo.majorVersion * 10 + _glinfo.minorVersion < 42) { - ss << "#extension GL_ARB_shader_image_load_store : enable" << std::endl - << "#extension GL_ARB_shading_language_420pack : enable" << std::endl; - } - if (_glinfo.fragment_interlock) - ss << "#extension GL_ARB_fragment_shader_interlock : enable" << std::endl - << "layout(pixel_interlock_ordered) in;" << std::endl; - else if (_glinfo.fragment_interlockNV) - ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl - << "layout(pixel_interlock_ordered) in;" << std::endl; - else if (_glinfo.fragment_ordering) - ss << "#extension GL_INTEL_fragment_shader_ordering : enable" << std::endl; + if (_glinfo.imageTextures) { + if (_glinfo.majorVersion * 10 + _glinfo.minorVersion < 42) { + ss << "#extension GL_ARB_shader_image_load_store : enable" << std::endl + << "#extension GL_ARB_shading_language_420pack : enable" << std::endl; + } + if (_glinfo.fragment_interlock) + ss << "#extension GL_ARB_fragment_shader_interlock : enable" << std::endl + << "layout(pixel_interlock_ordered) in;" << std::endl; + else if (_glinfo.fragment_interlockNV) + ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl + << "layout(pixel_interlock_ordered) in;" << std::endl; + else if (_glinfo.fragment_ordering) + ss << "#extension GL_INTEL_fragment_shader_ordering : enable" << std::endl; + } else if (_glinfo.ext_fetch) + ss << "#extension GL_EXT_shader_framebuffer_fetch : enable" << std::endl; } ss << "# define IN in" << std::endl << "# define OUT out" << std::endl @@ -790,8 +795,19 @@ public: "IN highp vec2 vTexCoord1;\n" "IN mediump vec2 vLodTexCoord;\n" "IN lowp float vNumLights; \n" - "OUT lowp vec4 fragColor; \n" - ; + ; + + if (config.frameBufferEmulation.N64DepthCompare != 0 && _glinfo.ext_fetch) { + m_part += + "layout(location = 0) OUT lowp vec4 fragColor; \n" + "layout(location = 1) inout highp vec4 depthZ; \n" + "layout(location = 2) inout highp vec4 depthDeltaZ; \n" + ; + } else { + m_part += + "OUT lowp vec4 fragColor; \n" + ; + } } }; @@ -855,7 +871,19 @@ public: m_part += "IN lowp vec4 vShadeColor; \n" "IN lowp float vNumLights; \n" - "OUT lowp vec4 fragColor; \n"; + ; + + if (config.frameBufferEmulation.N64DepthCompare != 0 && _glinfo.ext_fetch) { + m_part += + "layout(location = 0) OUT lowp vec4 fragColor; \n" + "layout(location = 1) inout highp vec4 depthZ; \n" + "layout(location = 2) inout highp vec4 depthDeltaZ; \n" + ; + } else { + m_part += + "OUT lowp vec4 fragColor; \n" + ; + } } }; @@ -955,13 +983,16 @@ public: ShaderFragmentHeaderDepthCompare(const opengl::GLInfo & _glinfo) { if (config.frameBufferEmulation.N64DepthCompare != 0) { - - m_part += - "layout(binding = 2, r32f) highp uniform restrict image2D uDepthImageZ; \n" - "layout(binding = 3, r32f) highp uniform restrict image2D uDepthImageDeltaZ;\n" - "bool depth_compare(highp float curZ);\n" - "bool depth_render(highp float Z, highp float curZ);\n"; - ; + m_part = + "bool depth_compare(highp float curZ); \n" + "bool depth_render(highp float Z, highp float curZ); \n" + ; + if (_glinfo.imageTextures) { + m_part += + "layout(binding = 2, r32f) highp uniform restrict image2D uDepthImageZ; \n" + "layout(binding = 3, r32f) highp uniform restrict image2D uDepthImageDeltaZ; \n" + ; + } } } }; @@ -1333,22 +1364,26 @@ public: if (config.frameBufferEmulation.N64DepthCompare != 0) { m_part = " bool should_discard = false; \n"; - if (_glinfo.fragment_interlock) - m_part += " beginInvocationInterlockARB(); \n"; - else if (_glinfo.fragment_interlockNV) - m_part += " beginInvocationInterlockNV(); \n"; - else if (_glinfo.fragment_ordering) - m_part += " beginFragmentShaderOrderingINTEL(); \n"; + if (_glinfo.imageTextures) { + if (_glinfo.fragment_interlock) + m_part += " beginInvocationInterlockARB(); \n"; + else if (_glinfo.fragment_interlockNV) + m_part += " beginInvocationInterlockNV(); \n"; + else if (_glinfo.fragment_ordering) + m_part += " beginFragmentShaderOrderingINTEL(); \n"; + } m_part += " if (uRenderTarget != 0) { if (!depth_render(fragColor.r, fragDepth)) should_discard = true; } \n" " else if (!depth_compare(fragDepth)) should_discard = true; \n" ; - if (_glinfo.fragment_interlock) - m_part += " endInvocationInterlockARB(); \n"; - else if (_glinfo.fragment_interlockNV) - m_part += " endInvocationInterlockNV(); \n"; + if (_glinfo.imageTextures) { + if (_glinfo.fragment_interlock) + m_part += " endInvocationInterlockARB(); \n"; + else if (_glinfo.fragment_interlockNV) + m_part += " endInvocationInterlockNV(); \n"; + } m_part += " if (should_discard) discard; \n"; @@ -1918,9 +1953,15 @@ public: "uniform mediump float uDeltaZ; \n" "bool depth_compare(highp float curZ) \n" "{ \n" - " ivec2 coord = ivec2(gl_FragCoord.xy); \n" - " highp vec4 depthZ = imageLoad(uDepthImageZ,coord); \n" - " highp vec4 depthDeltaZ = imageLoad(uDepthImageDeltaZ,coord);\n" + ; + if (_glinfo.imageTextures) { + m_part += + " ivec2 coord = ivec2(gl_FragCoord.xy); \n" + " highp vec4 depthZ = imageLoad(uDepthImageZ,coord); \n" + " highp vec4 depthDeltaZ = imageLoad(uDepthImageDeltaZ,coord);\n" + ; + } + m_part += " highp float bufZ = depthZ.r; \n" " highp float dz, dzMin; \n" " if (uDepthSource == 1) { \n" @@ -1950,10 +1991,21 @@ public: " break; \n" " } \n" " if (uEnableDepthUpdate != 0 && bRes) { \n" - " highp vec4 depthOutZ = vec4(curZ, 1.0, 1.0, 1.0); \n" - " highp vec4 depthOutDeltaZ = vec4(dz, 1.0, 1.0, 1.0); \n" - " imageStore(uDepthImageZ, coord, depthOutZ); \n" - " imageStore(uDepthImageDeltaZ, coord, depthOutDeltaZ);\n" + ; + if (_glinfo.imageTextures) { + m_part += + " highp vec4 depthOutZ = vec4(curZ, 1.0, 1.0, 1.0); \n" + " highp vec4 depthOutDeltaZ = vec4(dz, 1.0, 1.0, 1.0); \n" + " imageStore(uDepthImageZ, coord, depthOutZ); \n" + " imageStore(uDepthImageDeltaZ, coord, depthOutDeltaZ); \n" + ; + } else if (_glinfo.ext_fetch) { + m_part += + " depthZ.r = curZ; \n" + " depthDeltaZ.r = dz; \n" + ; + } + m_part += " } \n" " if (uEnableDepthCompare != 0) \n" " return bRes; \n" @@ -1975,17 +2027,34 @@ public: "{ \n" " ivec2 coord = ivec2(gl_FragCoord.xy); \n" " if (uEnableDepthCompare != 0) { \n" - " highp vec4 depthZ = imageLoad(uDepthImageZ,coord); \n" + ; + if (_glinfo.imageTextures) { + m_part += + " highp vec4 depthZ = imageLoad(uDepthImageZ,coord); \n" + ; + } + m_part += " highp float bufZ = depthZ.r; \n" " if (curZ >= bufZ) return false; \n" " } \n" - " highp vec4 depthOutZ = vec4(Z, 1.0, 1.0, 1.0); \n" - " highp vec4 depthOutDeltaZ = vec4(0.0, 1.0, 1.0, 1.0);\n" - " imageStore(uDepthImageZ,coord, depthOutZ); \n" - " imageStore(uDepthImageDeltaZ,coord, depthOutDeltaZ); \n" + ; + if (_glinfo.imageTextures) { + m_part += + " highp vec4 depthOutZ = vec4(Z, 1.0, 1.0, 1.0); \n" + " highp vec4 depthOutDeltaZ = vec4(0.0, 1.0, 1.0, 1.0);\n" + " imageStore(uDepthImageZ,coord, depthOutZ); \n" + " imageStore(uDepthImageDeltaZ,coord, depthOutDeltaZ); \n" + ; + } else if (_glinfo.ext_fetch) { + m_part += + " depthZ.r = Z; \n" + " depthDeltaZ.r = 0.0; \n" + ; + } + m_part += " return true; \n" "} \n" - ; + ; } } }; diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h b/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h index 9a987bed..6a83d523 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h +++ b/src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h @@ -20,7 +20,7 @@ namespace glsl { bool _saveCombinerKeys(const graphics::Combiners & _combiners) const; bool _loadFromCombinerKeys(graphics::Combiners & _combiners); - const u32 m_formatVersion = 0x1EU; + const u32 m_formatVersion = 0x1FU; const u32 m_keysFormatVersion = 0x04; const opengl::GLInfo & m_glinfo; opengl::CachedUseProgram * m_useProgram; diff --git a/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp b/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp index 4e494489..1046d6ce 100644 --- a/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp +++ b/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp @@ -1,3 +1,5 @@ +#include + #include "GLFunctions.h" #include "opengl_GLInfo.h" #include "opengl_CachedFunctions.h" @@ -21,9 +23,15 @@ void CachedEnable::enable(bool _enable) return; if (_enable) { - glEnable(GLenum(m_parameter)); + if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(glEnablei)) + glEnablei(GLenum(m_parameter), 0); + else + glEnable(GLenum(m_parameter)); } else { - glDisable(GLenum(m_parameter)); + if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(glDisablei)) + glDisablei(GLenum(m_parameter), 0); + else + glDisable(GLenum(m_parameter)); } } diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp index 5427ce39..a6e49fb2 100644 --- a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp +++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp @@ -161,8 +161,13 @@ void ContextImpl::clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha) CachedEnable * enableScissor = m_cachedFunctions->getCachedEnable(graphics::enable::SCISSOR_TEST); enableScissor->enable(false); - m_cachedFunctions->getCachedClearColor()->setClearColor(_red, _green, _blue, _alpha); - glClear(GL_COLOR_BUFFER_BIT); + if (m_glInfo.isGLES2) { + m_cachedFunctions->getCachedClearColor()->setClearColor(_red, _green, _blue, _alpha); + glClear(GL_COLOR_BUFFER_BIT); + } else { + GLfloat values[4] = {_red, _green, _blue, _alpha}; + glClearBufferfv(GL_COLOR, 0, values); + } enableScissor->enable(true); } @@ -255,8 +260,7 @@ s32 ContextImpl::getMaxTextureSize() const void ContextImpl::bindImageTexture(const graphics::Context::BindImageTextureParameters & _params) { - if (IS_GL_FUNCTION_VALID(glBindImageTexture)) - glBindImageTexture(GLuint(_params.imageUnit), GLuint(_params.texture), 0, GL_FALSE, 0, GLenum(_params.accessMode), GLenum(_params.textureFormat)); + glBindImageTexture(GLuint(_params.imageUnit), GLuint(_params.texture), 0, GL_FALSE, 0, GLenum(_params.accessMode), GLenum(_params.textureFormat)); } u32 ContextImpl::convertInternalTextureFormat(u32 _format) const @@ -336,6 +340,12 @@ bool ContextImpl::blitFramebuffers(const graphics::Context::BlitFramebuffersPara return m_blitFramebuffers->blitFramebuffers(_params); } +void ContextImpl::setDrawBuffers(u32 _num) +{ + GLenum targets[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; + glDrawBuffers(_num, targets); +} + graphics::PixelReadBuffer * ContextImpl::createPixelReadBuffer(size_t _sizeInBytes) { if (m_createPixelReadBuffer) @@ -479,6 +489,8 @@ bool ContextImpl::isSupported(graphics::SpecialFeatures _feature) const return !m_glInfo.isGLES2; case graphics::SpecialFeatures::ClipControl: return !m_glInfo.isGLESX; + case graphics::SpecialFeatures::FramebufferFetch: + return m_glInfo.ext_fetch; } return false; } diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.h b/src/Graphics/OpenGLContext/opengl_ContextImpl.h index 91a03a13..eda5c8bd 100644 --- a/src/Graphics/OpenGLContext/opengl_ContextImpl.h +++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.h @@ -96,6 +96,8 @@ namespace opengl { bool blitFramebuffers(const graphics::Context::BlitFramebuffersParams & _params) override; + void setDrawBuffers(u32 _num) override; + /*---------------Pixelbuffer-------------*/ graphics::PixelReadBuffer * createPixelReadBuffer(size_t _sizeInBytes) override; diff --git a/src/Graphics/OpenGLContext/opengl_GLInfo.cpp b/src/Graphics/OpenGLContext/opengl_GLInfo.cpp index d171bc33..8f97b92f 100644 --- a/src/Graphics/OpenGLContext/opengl_GLInfo.cpp +++ b/src/Graphics/OpenGLContext/opengl_GLInfo.cpp @@ -47,11 +47,11 @@ void GLInfo::init() { imageTextures = false; msaa = false; } else if (isGLESX) { - imageTextures = (numericVersion >= 31) && IS_GL_FUNCTION_VALID(glBindImageTexture); + imageTextures = (numericVersion >= 31); msaa = numericVersion >= 31; } else { imageTextures = ((numericVersion >= 43) || (Utils::isExtensionSupported(*this, "GL_ARB_shader_image_load_store") && - Utils::isExtensionSupported(*this, "GL_ARB_compute_shader"))) && IS_GL_FUNCTION_VALID(glBindImageTexture); + Utils::isExtensionSupported(*this, "GL_ARB_compute_shader"))); msaa = true; } @@ -59,12 +59,7 @@ void GLInfo::init() { fragment_interlockNV = Utils::isExtensionSupported(*this, "GL_NV_fragment_shader_interlock") && !fragment_interlock; fragment_ordering = Utils::isExtensionSupported(*this, "GL_INTEL_fragment_shader_ordering") && !fragment_interlock && !fragment_interlockNV; - if (config.frameBufferEmulation.N64DepthCompare != 0) { - if (!(imageTextures && (fragment_interlock || fragment_interlockNV || fragment_ordering))) { - config.frameBufferEmulation.N64DepthCompare = 0; - LOG(LOG_WARNING, "Your GPU does not support the extensions needed for N64 Depth Compare.\n"); - } - } + imageTextures = imageTextures && (fragment_interlock || fragment_interlockNV || fragment_ordering); if (isGLES2) config.generalEmulation.enableFragmentDepthWrite = 0; @@ -87,12 +82,23 @@ void GLInfo::init() { } } + bool ext_draw_buffers_indexed = isGLESX && (Utils::isExtensionSupported(*this, "GL_EXT_draw_buffers_indexed") || numericVersion >= 32); #ifdef EGL if (isGLESX && bufferStorage) g_glBufferStorage = (PFNGLBUFFERSTORAGEPROC) eglGetProcAddress("glBufferStorageEXT"); + if (isGLESX && numericVersion < 32) { + if (ext_draw_buffers_indexed) { + g_glEnablei = (PFNGLENABLEIPROC) eglGetProcAddress("glEnableiEXT"); + g_glDisablei = (PFNGLDISABLEIPROC) eglGetProcAddress("glDisableiEXT"); + } else { + g_glEnablei = nullptr; + g_glDisablei = nullptr; + } + } if (isGLES2 && shaderStorage) { g_glProgramBinary = (PFNGLPROGRAMBINARYPROC) eglGetProcAddress("glProgramBinaryOES"); g_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) eglGetProcAddress("glGetProgramBinaryOES"); + g_glProgramParameteri = nullptr; } #endif #ifndef OS_ANDROID @@ -114,4 +120,13 @@ void GLInfo::init() { fetch_depth = Utils::isExtensionSupported(*this, "GL_ARM_shader_framebuffer_fetch_depth_stencil"); texture_barrier = (!isGLESX && numericVersion >= 45) || Utils::isExtensionSupported(*this, "GL_ARB_texture_barrier"); texture_barrierNV = Utils::isExtensionSupported(*this, "GL_NV_texture_barrier"); + + ext_fetch = Utils::isExtensionSupported(*this, "GL_EXT_shader_framebuffer_fetch") && !isGLES2 && (!isGLESX || ext_draw_buffers_indexed) && !imageTextures; + + if (config.frameBufferEmulation.N64DepthCompare != 0) { + if (!imageTextures && !ext_fetch) { + config.frameBufferEmulation.N64DepthCompare = 0; + LOG(LOG_WARNING, "Your GPU does not support the extensions needed for N64 Depth Compare.\n"); + } + } } diff --git a/src/Graphics/OpenGLContext/opengl_GLInfo.h b/src/Graphics/OpenGLContext/opengl_GLInfo.h index f47f1d04..60f4f876 100644 --- a/src/Graphics/OpenGLContext/opengl_GLInfo.h +++ b/src/Graphics/OpenGLContext/opengl_GLInfo.h @@ -31,6 +31,7 @@ struct GLInfo { bool fragment_interlock = false; bool fragment_interlockNV = false; bool fragment_ordering = false; + bool ext_fetch = false; Renderer renderer = Renderer::Other; void init(); diff --git a/src/Graphics/OpenGLContext/opengl_Parameters.cpp b/src/Graphics/OpenGLContext/opengl_Parameters.cpp index c176199d..eee3380e 100644 --- a/src/Graphics/OpenGLContext/opengl_Parameters.cpp +++ b/src/Graphics/OpenGLContext/opengl_Parameters.cpp @@ -50,6 +50,8 @@ namespace graphics { namespace bufferAttachment { BufferAttachmentParam COLOR_ATTACHMENT0(GL_COLOR_ATTACHMENT0); + BufferAttachmentParam COLOR_ATTACHMENT1(GL_COLOR_ATTACHMENT1); + BufferAttachmentParam COLOR_ATTACHMENT2(GL_COLOR_ATTACHMENT2); BufferAttachmentParam DEPTH_ATTACHMENT(GL_DEPTH_ATTACHMENT); } diff --git a/src/Graphics/Parameters.h b/src/Graphics/Parameters.h index 3410ed71..b98bd376 100644 --- a/src/Graphics/Parameters.h +++ b/src/Graphics/Parameters.h @@ -50,6 +50,8 @@ namespace graphics { namespace bufferAttachment { extern BufferAttachmentParam COLOR_ATTACHMENT0; + extern BufferAttachmentParam COLOR_ATTACHMENT1; + extern BufferAttachmentParam COLOR_ATTACHMENT2; extern BufferAttachmentParam DEPTH_ATTACHMENT; }