unity_native_render_plugin/NativeRenderPlugin/RenderAPI_OpenGLCoreES.cpp
2024-11-22 12:09:31 +08:00

294 lines
8.1 KiB
C++

#include "RenderAPI.h"
#include "PlatformBase.h"
#include <stdio.h>
// OpenGL Core profile (desktop) or OpenGL ES (mobile) implementation of RenderAPI.
// Supports several flavors: Core, ES2, ES3
#if SUPPORT_OPENGL_UNIFIED
#include "Unity/IUnityRenderingExtensions.h"
#include <assert.h>
#if UNITY_IOS || UNITY_TVOS
#include <OpenGLES/ES2/gl.h>
#elif UNITY_ANDROID || UNITY_WEBGL || OHOS
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#if OHOS
#include <xengine/xeg_gles_extension.h>
#include "xengine/xeg_gles_spatial_upscale.h"
#include "xengine/xeg_gles_adaptive_vrs.h"
#include "xengine/xeg_gles_neural_upscale.h"
#include <native_buffer/native_buffer.h>
#include <native_window/external_window.h>
#endif
#elif UNITY_OSX
#include <OpenGL/gl3.h>
#elif UNITY_WIN
// On Windows, use gl3w to initialize and load OpenGL Core functions. In principle any other
// library (like GLEW, GLFW etc.) can be used; here we use gl3w since it's simple and
// straightforward.
#include "gl3w/gl3w.h"
#elif UNITY_LINUX
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#elif UNITY_EMBEDDED_LINUX
#include <GLES2/gl2.h>
#if SUPPORT_OPENGL_CORE
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#endif
#elif UNITY_QNX
#include <GLES2/gl2.h>
#else
#error Unknown platform
#endif
#include <string.h>
extern void unityLog(const char *msg);
typedef void(GL_APIENTRYP PFNGLSHADINGRATE)(GLenum rate);
typedef void (GL_APIENTRYP PFNGLQCOMFRAMEEXTRAPOLATION) (GLuint src1, GLuint src2, GLuint output, float scaleFactor);
class RenderAPI_OpenGLCoreES : public RenderAPI
{
public:
RenderAPI_OpenGLCoreES(UnityGfxRenderer api_type);
virtual ~RenderAPI_OpenGLCoreES() {}
virtual void processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces *interfaces) override;
virtual bool getUsesReverseZ() override { return false; }
virtual void enableVRS(int vrsEnum) override;
virtual void disableVRS() override;
virtual void enableFGExtrapolation() override;
virtual void preFGExtrapolation() override;
virtual bool doFGExtrapolation(void *src, void *data, void *dst) override;
virtual void postFGExtrapolation() override;
virtual void disableFGExtrapolation() override;
virtual void spatialUpScale(void *src, void *data, void *dst) override;
private:
virtual void initSupportFeature() override;
UnityGfxRenderer m_api_type;
PFNGLSHADINGRATE gl_shadingrate_fn = nullptr;
PFNGLQCOMFRAMEEXTRAPOLATION gl_extrapolate_qcom_fn;
};
// 重新定义 vrs rate
/*
QCOM_shading_rate
SHADING_RATE_1X1_PIXELS_QCOM 0x96A6
SHADING_RATE_1X2_PIXELS_QCOM 0x96A7
SHADING_RATE_2X1_PIXELS_QCOM 0x96A8
SHADING_RATE_2X2_PIXELS_QCOM 0x96A9
SHADING_RATE_4X2_PIXELS_QCOM 0x96AC
SHADING_RATE_4X4_PIXELS_QCOM 0x96AE
*/
#define SHADING_RATE_1X1_PIXELS_EXT 0x96A6
#define SHADING_RATE_1X2_PIXELS_EXT 0x96A7
#define SHADING_RATE_2X1_PIXELS_EXT 0x96A8
#define SHADING_RATE_2X2_PIXELS_EXT 0x96A9
#define SHADING_RATE_1X4_PIXELS_EXT 0x96AA
#define SHADING_RATE_4X1_PIXELS_EXT 0x96AB
#define SHADING_RATE_4X2_PIXELS_EXT 0x96AC
#define SHADING_RATE_2X4_PIXELS_EXT 0x96AD
#define SHADING_RATE_4X4_PIXELS_EXT 0x96AE
// TODO: glGetFragmentShadingRatesEXT 检查支持的项
static GLenum vrs_argment_size_table[] =
{
SHADING_RATE_1X1_PIXELS_EXT,
SHADING_RATE_2X1_PIXELS_EXT,
SHADING_RATE_1X2_PIXELS_EXT,
SHADING_RATE_2X2_PIXELS_EXT,
SHADING_RATE_4X2_PIXELS_EXT,
SHADING_RATE_2X4_PIXELS_EXT,
SHADING_RATE_4X4_PIXELS_EXT,
// SHADING_RATE_1X4_PIXELS_EXT, //(此硬件原生不支持)
// SHADING_RATE_4X1_PIXELS_EXT,// (此硬件原生不支持)
};
RenderAPI *CreateRenderAPI_OpenGLCoreES(UnityGfxRenderer api_type)
{
return new RenderAPI_OpenGLCoreES(api_type);
}
RenderAPI_OpenGLCoreES::RenderAPI_OpenGLCoreES(UnityGfxRenderer api_type)
: m_api_type(api_type)
{
}
void RenderAPI_OpenGLCoreES::processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces *interfaces)
{
if (type == kUnityGfxDeviceEventInitialize)
{
initSupportFeature();
}
else if (type == kUnityGfxDeviceEventShutdown)
{
//@TODO: release resources
}
}
void RenderAPI_OpenGLCoreES::initSupportFeature()
{
#ifdef GL_EXT_fragment_shading_rate
support_features[GraphicsFeature::VRS_DRAW] = true;
gl_shadingrate_fn = glShadingRateEXT;
#endif // GL_EXT_fragment_shading_rate
#ifdef GL_EXT_fragment_shading_rate_primitive
support_features[GraphicsFeature::VRS_PRIMITIVE] = true;
#endif // GL_EXT_fragment_shading_rate_primitive
#ifdef GL_EXT_fragment_shading_rate_attachment
support_features[GraphicsFeature::VRS_ATTACHMENT] = true;
#endif // GL_EXT_fragment_shading_rate_attachment
const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
if (strstr(extensions, "GL_EXT_fragment_shading_rate") || strstr(extensions, "GL_QCOM_shading_rate"))
{
support_features[GraphicsFeature::VRS_DRAW] = true;
}
if (strstr(extensions, "GL_EXT_fragment_shading_rate_primitive"))
{
support_features[GraphicsFeature::VRS_PRIMITIVE] = true;
}
if (strstr(extensions, "GL_EXT_fragment_shading_rate_attachment"))
{
support_features[GraphicsFeature::VRS_ATTACHMENT] = true;
}
if (support_features[GraphicsFeature::VRS_DRAW])
{
if (gl_shadingrate_fn == nullptr)
{
gl_shadingrate_fn = (PFNGLSHADINGRATE)((void *)eglGetProcAddress("glShadingRateQCOM"));
if (gl_shadingrate_fn == nullptr)
{
gl_shadingrate_fn = (PFNGLSHADINGRATE)((void *)eglGetProcAddress("glShadingRateEXT"));
if (gl_shadingrate_fn == nullptr)
{
support_features[GraphicsFeature::VRS_DRAW] = false;
}
}
}
}
if (strstr(extensions, "GL_QCOM_frame_extrapolation"))
{
support_features[GraphicsFeature::QCOM_AFME] = true;
gl_extrapolate_qcom_fn = (PFNGLQCOMFRAMEEXTRAPOLATION)eglGetProcAddress("glExtrapolateTex2DQCOM");
}
#if OHOS
extensions = (const char *)HMS_XEG_GetString(XEG_EXTENSIONS);
if (strstr(extensions, XEG_SPATIAL_UPSCALE_EXTENSION_NAME))
{
support_features[GraphicsFeature::HW_SPATIAL_SR] = true;
}
if (strstr(extensions, XEG_NEURAL_UPSCALE_EXTENSION_NAME))
{
support_features[GraphicsFeature::HW_AISR] = true;
}
if (strstr(extensions, XEG_ADAPTIVE_VRS_EXTENSION_NAME))
{
support_features[GraphicsFeature::HW_ADAPTIVE_VRS] = true;
}
#endif
char buf[40];
for (size_t i = 0; i < GraphicsFeature::MAX_CNT; i++)
{
sprintf(buf, "GraphicsFeature: %d \n", support_features[(GraphicsFeature)i]);
unityLog(buf);
}
}
void RenderAPI_OpenGLCoreES::enableVRS(int vrs_enum)
{
gl_shadingrate_fn(vrs_argment_size_table[vrs_enum]);
}
void RenderAPI_OpenGLCoreES::disableVRS()
{
gl_shadingrate_fn(vrs_argment_size_table[0]);
}
void RenderAPI_OpenGLCoreES::enableFGExtrapolation()
{
}
void RenderAPI_OpenGLCoreES::preFGExtrapolation()
{
}
bool RenderAPI_OpenGLCoreES::doFGExtrapolation(void *src, void *data, void *dst)
{
GLuint gl_src0tex = (GLuint)(size_t)(src);
GLuint gl_src1tex = (GLuint)(size_t)(data);
GLuint gl_dsttex = (GLuint)(size_t)(dst);
gl_extrapolate_qcom_fn(gl_src0tex, gl_src1tex, gl_dsttex, 0.5f);
auto err = glGetError();
return err == GL_NO_ERROR;
}
void RenderAPI_OpenGLCoreES::postFGExtrapolation()
{
}
void RenderAPI_OpenGLCoreES::disableFGExtrapolation()
{
}
void RenderAPI_OpenGLCoreES::spatialUpScale(void *src, void *data, void *dst)
{
#if OHOS
struct HWSpatialSRParam
{
float sharpness;
uint32_t render_width;
uint32_t render_height;
};
if (data != NULL)
{
HWSpatialSRParam* param = (HWSpatialSRParam*) data;
float m_sharpness = param->sharpness;
HMS_XEG_SpatialUpscaleParameter(XEG_SPATIAL_UPSCALE_SHARPNESS, &m_sharpness);
// upscaleScissor为超分输入图像的采样区域
int upscaleScissor[4] = {0, 0, static_cast<int>(param->render_width), static_cast<int>(param->render_height)};
HMS_XEG_SpatialUpscaleParameter(XEG_SPATIAL_UPSCALE_SCISSOR, upscaleScissor);
}
GLuint gl_srctex = (GLuint)(size_t)(src);
// TODO: 测试由上层设置
// GLuint gl_dsttex = (GLuint)(size_t)(dst);
// // upscaleFBO为用户自定义创建的framebuffer
// glBindFramebuffer(GL_FRAMEBUFFER, gl_dsttex);
// glViewport(0, 0, upscale_width, upscale_height);
// glScissor(0, 0, upscale_width, upscale_height);
HMS_XEG_RenderSpatialUpscale(gl_srctex);
#endif
}
#endif // #if SUPPORT_OPENGL_UNIFIED