#include "RenderAPI.h" #include "PlatformBase.h" #include // 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 #if UNITY_IOS || UNITY_TVOS #include #elif UNITY_ANDROID || UNITY_WEBGL || OHOS #define GL_GLEXT_PROTOTYPES #include #include #include #if OHOS #include #include "xengine/xeg_gles_spatial_upscale.h" #include "xengine/xeg_gles_adaptive_vrs.h" #include "xengine/xeg_gles_neural_upscale.h" #include #include #endif #elif UNITY_OSX #include #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 #elif UNITY_EMBEDDED_LINUX #include #if SUPPORT_OPENGL_CORE #define GL_GLEXT_PROTOTYPES #include #endif #elif UNITY_QNX #include #else #error Unknown platform #endif #include 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(param->render_width), static_cast(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