diff options
author | Germano Cavalcante <mano-wii> | 2021-05-14 17:15:00 +0300 |
---|---|---|
committer | Germano Cavalcante <germano.costa@ig.com.br> | 2021-05-14 18:26:40 +0300 |
commit | 48fa029dd11bb09d4aca8e0a420781e3ec07a3a2 (patch) | |
tree | 7ea87a8fb24dc7201fb1a2a52a681973a9c0d46e | |
parent | 3f4f109646059ee0780bb40dbd65b3bc8c3a8f3f (diff) |
Python GPU: New 'platform' module
This module exposes the platform utils defined in the GPU module in C.
This will be useful for porting existing code with `bgl` to `gpu`.
Reviewed By: fclem, brecht, campbellbarton
Maniphest Tasks: T80730
Part of D11147
-rw-r--r-- | source/blender/gpu/GPU_platform.h | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_platform.cc | 73 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_platform_private.hh | 16 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 77 | ||||
-rw-r--r-- | source/blender/python/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.c | 4 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_platform.c | 81 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_platform.h | 23 |
8 files changed, 223 insertions, 56 deletions
diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h index c457b829bf7..fa7d5d7fba8 100644 --- a/source/blender/gpu/GPU_platform.h +++ b/source/blender/gpu/GPU_platform.h @@ -68,6 +68,9 @@ extern "C" { bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver); eGPUSupportLevel GPU_platform_support_level(void); +const char *GPU_platform_vendor(void); +const char *GPU_platform_renderer(void); +const char *GPU_platform_version(void); const char *GPU_platform_support_level_key(void); const char *GPU_platform_gpu_name(void); diff --git a/source/blender/gpu/intern/gpu_platform.cc b/source/blender/gpu/intern/gpu_platform.cc index 6b9878f2ba4..49dde473300 100644 --- a/source/blender/gpu/intern/gpu_platform.cc +++ b/source/blender/gpu/intern/gpu_platform.cc @@ -41,10 +41,10 @@ namespace blender::gpu { GPUPlatformGlobal GPG; -void GPUPlatformGlobal::create_key(eGPUSupportLevel support_level, - const char *vendor, - const char *renderer, - const char *version) +static char *create_key(eGPUSupportLevel support_level, + const char *vendor, + const char *renderer, + const char *version) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_appendf(ds, "{%s/%s/%s}=", vendor, renderer, version); @@ -58,29 +58,56 @@ void GPUPlatformGlobal::create_key(eGPUSupportLevel support_level, BLI_dynstr_append(ds, "UNSUPPORTED"); } - support_key = BLI_dynstr_get_cstring(ds); + char *support_key = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); BLI_str_replace_char(support_key, '\n', ' '); BLI_str_replace_char(support_key, '\r', ' '); + return support_key; } -void GPUPlatformGlobal::create_gpu_name(const char *vendor, - const char *renderer, - const char *version) +static char *create_gpu_name(const char *vendor, const char *renderer, const char *version) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_appendf(ds, "%s %s %s", vendor, renderer, version); - gpu_name = BLI_dynstr_get_cstring(ds); + char *gpu_name = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); BLI_str_replace_char(gpu_name, '\n', ' '); BLI_str_replace_char(gpu_name, '\r', ' '); + return gpu_name; +} + +void GPUPlatformGlobal::init(eGPUDeviceType gpu_device, + eGPUOSType os_type, + eGPUDriverType driver_type, + eGPUSupportLevel gpu_support_level, + const char *vendor_str, + const char *renderer_str, + const char *version_str) +{ + this->clear(); + + this->initialized = true; + + this->device = gpu_device; + this->os = os_type; + this->driver = driver_type; + this->support_level = gpu_support_level; + + this->vendor = BLI_strdup(vendor_str); + this->renderer = BLI_strdup(renderer_str); + this->version = BLI_strdup(version_str); + this->support_key = create_key(gpu_support_level, vendor_str, renderer_str, version_str); + this->gpu_name = create_gpu_name(vendor_str, renderer_str, version_str); } void GPUPlatformGlobal::clear() { - MEM_SAFE_FREE(GPG.support_key); - MEM_SAFE_FREE(GPG.gpu_name); + MEM_SAFE_FREE(vendor); + MEM_SAFE_FREE(renderer); + MEM_SAFE_FREE(version); + MEM_SAFE_FREE(support_key); + MEM_SAFE_FREE(gpu_name); initialized = false; } @@ -96,22 +123,44 @@ using namespace blender::gpu; eGPUSupportLevel GPU_platform_support_level() { + BLI_assert(GPG.initialized); return GPG.support_level; } -const char *GPU_platform_support_level_key() +const char *GPU_platform_vendor(void) +{ + BLI_assert(GPG.initialized); + return GPG.vendor; +} + +const char *GPU_platform_renderer(void) +{ + BLI_assert(GPG.initialized); + return GPG.renderer; +} + +const char *GPU_platform_version(void) +{ + BLI_assert(GPG.initialized); + return GPG.version; +} + +const char *GPU_platform_support_level_key(void) { + BLI_assert(GPG.initialized); return GPG.support_key; } const char *GPU_platform_gpu_name(void) { + BLI_assert(GPG.initialized); return GPG.gpu_name; } /* GPU Types */ bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver) { + BLI_assert(GPG.initialized); return (GPG.device & device) && (GPG.os & os) && (GPG.driver & driver); } diff --git a/source/blender/gpu/intern/gpu_platform_private.hh b/source/blender/gpu/intern/gpu_platform_private.hh index 02d99efa4a9..f823269ab54 100644 --- a/source/blender/gpu/intern/gpu_platform_private.hh +++ b/source/blender/gpu/intern/gpu_platform_private.hh @@ -34,16 +34,20 @@ class GPUPlatformGlobal { eGPUOSType os; eGPUDriverType driver; eGPUSupportLevel support_level; + char *vendor = nullptr; + char *renderer = nullptr; + char *version = nullptr; char *support_key = nullptr; char *gpu_name = nullptr; public: - void create_key(eGPUSupportLevel support_level, - const char *vendor, - const char *renderer, - const char *version); - - void create_gpu_name(const char *vendor, const char *renderer, const char *version); + void init(eGPUDeviceType gpu_device, + eGPUOSType os_type, + eGPUDriverType driver_type, + eGPUSupportLevel gpu_support_level, + const char *vendor_str, + const char *renderer_str, + const char *version_str); void clear(void); }; diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 89bad1c9a4b..9d9cc62c633 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -41,39 +41,42 @@ namespace blender::gpu { void GLBackend::platform_init() { BLI_assert(!GPG.initialized); - GPG.initialized = true; + + const char *vendor = (const char *)glGetString(GL_VENDOR); + const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *version = (const char *)glGetString(GL_VERSION); + eGPUDeviceType device = GPU_DEVICE_ANY; + eGPUOSType os = GPU_OS_ANY; + eGPUDriverType driver = GPU_DRIVER_ANY; + eGPUSupportLevel support_level = GPU_SUPPORT_LEVEL_SUPPORTED; #ifdef _WIN32 - GPG.os = GPU_OS_WIN; + os = GPU_OS_WIN; #elif defined(__APPLE__) - GPG.os = GPU_OS_MAC; + os = GPU_OS_MAC; #else - GPG.os = GPU_OS_UNIX; + os = GPU_OS_UNIX; #endif - const char *vendor = (const char *)glGetString(GL_VENDOR); - const char *renderer = (const char *)glGetString(GL_RENDERER); - const char *version = (const char *)glGetString(GL_VERSION); - if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) { - GPG.device = GPU_DEVICE_ATI; - GPG.driver = GPU_DRIVER_OFFICIAL; + device = GPU_DEVICE_ATI; + driver = GPU_DRIVER_OFFICIAL; } else if (strstr(vendor, "NVIDIA")) { - GPG.device = GPU_DEVICE_NVIDIA; - GPG.driver = GPU_DRIVER_OFFICIAL; + device = GPU_DEVICE_NVIDIA; + driver = GPU_DRIVER_OFFICIAL; } else if (strstr(vendor, "Intel") || /* src/mesa/drivers/dri/intel/intel_context.c */ strstr(renderer, "Mesa DRI Intel") || strstr(renderer, "Mesa DRI Mobile Intel")) { - GPG.device = GPU_DEVICE_INTEL; - GPG.driver = GPU_DRIVER_OFFICIAL; + device = GPU_DEVICE_INTEL; + driver = GPU_DRIVER_OFFICIAL; if (strstr(renderer, "UHD Graphics") || /* Not UHD but affected by the same bugs. */ strstr(renderer, "HD Graphics 530") || strstr(renderer, "Kaby Lake GT2") || strstr(renderer, "Whiskey Lake")) { - GPG.device |= GPU_DEVICE_INTEL_UHD; + device |= GPU_DEVICE_INTEL_UHD; } } else if ((strstr(renderer, "Mesa DRI R")) || @@ -81,49 +84,47 @@ void GLBackend::platform_init() (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) { - GPG.device = GPU_DEVICE_ATI; - GPG.driver = GPU_DRIVER_OPENSOURCE; + device = GPU_DEVICE_ATI; + driver = GPU_DRIVER_OPENSOURCE; } else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) { - GPG.device = GPU_DEVICE_NVIDIA; - GPG.driver = GPU_DRIVER_OPENSOURCE; + device = GPU_DEVICE_NVIDIA; + driver = GPU_DRIVER_OPENSOURCE; } else if (strstr(vendor, "Mesa")) { - GPG.device = GPU_DEVICE_SOFTWARE; - GPG.driver = GPU_DRIVER_SOFTWARE; + device = GPU_DEVICE_SOFTWARE; + driver = GPU_DRIVER_SOFTWARE; } else if (strstr(vendor, "Microsoft")) { - GPG.device = GPU_DEVICE_SOFTWARE; - GPG.driver = GPU_DRIVER_SOFTWARE; + device = GPU_DEVICE_SOFTWARE; + driver = GPU_DRIVER_SOFTWARE; } else if (strstr(vendor, "Apple")) { /* Apple Silicon. */ - GPG.device = GPU_DEVICE_APPLE; - GPG.driver = GPU_DRIVER_OFFICIAL; + device = GPU_DEVICE_APPLE; + driver = GPU_DRIVER_OFFICIAL; } else if (strstr(renderer, "Apple Software Renderer")) { - GPG.device = GPU_DEVICE_SOFTWARE; - GPG.driver = GPU_DRIVER_SOFTWARE; + device = GPU_DEVICE_SOFTWARE; + driver = GPU_DRIVER_SOFTWARE; } else if (strstr(renderer, "llvmpipe") || strstr(renderer, "softpipe")) { - GPG.device = GPU_DEVICE_SOFTWARE; - GPG.driver = GPU_DRIVER_SOFTWARE; + device = GPU_DEVICE_SOFTWARE; + driver = GPU_DRIVER_SOFTWARE; } else { printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n"); printf("Detected OpenGL configuration:\n"); printf("Vendor: %s\n", vendor); printf("Renderer: %s\n", renderer); - GPG.device = GPU_DEVICE_ANY; - GPG.driver = GPU_DRIVER_ANY; } /* Detect support level */ if (!GLEW_VERSION_3_3) { - GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; + support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; } else { - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) { + if ((device & GPU_DEVICE_INTEL) && (os & GPU_OS_WIN)) { /* Old Intel drivers with known bugs that cause material properties to crash. * Version Build 10.18.14.5067 is the latest available and appears to be working * ok with our workarounds, so excluded from this list. */ @@ -132,19 +133,19 @@ void GLBackend::platform_init() strstr(version, "Build 9.18") || strstr(version, "Build 10.18.10.3") || strstr(version, "Build 10.18.10.4") || strstr(version, "Build 10.18.10.5") || strstr(version, "Build 10.18.14.4")) { - GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED; + support_level = GPU_SUPPORT_LEVEL_LIMITED; } } - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_ANY)) { + if ((device & GPU_DEVICE_ATI) && (os & GPU_OS_UNIX)) { /* Platform seems to work when SB backend is disabled. This can be done * by adding the environment variable `R600_DEBUG=nosb`. */ if (strstr(renderer, "AMD CEDAR")) { - GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED; + support_level = GPU_SUPPORT_LEVEL_LIMITED; } } - GPG.create_key(GPG.support_level, vendor, renderer, version); - GPG.create_gpu_name(vendor, renderer, version); } + + GPG.init(device, os, driver, support_level, vendor, renderer, version); } void GLBackend::platform_exit() diff --git a/source/blender/python/gpu/CMakeLists.txt b/source/blender/python/gpu/CMakeLists.txt index 9742664d107..1424b35a004 100644 --- a/source/blender/python/gpu/CMakeLists.txt +++ b/source/blender/python/gpu/CMakeLists.txt @@ -42,6 +42,7 @@ set(SRC gpu_py_framebuffer.c gpu_py_matrix.c gpu_py_offscreen.c + gpu_py_platform.c gpu_py_select.c gpu_py_shader.c gpu_py_state.c @@ -60,6 +61,7 @@ set(SRC gpu_py_framebuffer.h gpu_py_matrix.h gpu_py_offscreen.h + gpu_py_platform.h gpu_py_select.h gpu_py_shader.h gpu_py_state.h diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c index 18e5fa41c44..5119b3612f8 100644 --- a/source/blender/python/gpu/gpu_py_api.c +++ b/source/blender/python/gpu/gpu_py_api.c @@ -32,6 +32,7 @@ #include "gpu_py_capabilities.h" #include "gpu_py_matrix.h" +#include "gpu_py_platform.h" #include "gpu_py_select.h" #include "gpu_py_state.h" #include "gpu_py_types.h" @@ -68,6 +69,9 @@ PyObject *BPyInit_gpu(void) PyModule_AddObject(mod, "matrix", (submodule = bpygpu_matrix_init())); PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + PyModule_AddObject(mod, "platform", (submodule = bpygpu_platform_init())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + PyModule_AddObject(mod, "select", (submodule = bpygpu_select_init())); PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c new file mode 100644 index 00000000000..5247646fcb6 --- /dev/null +++ b/source/blender/python/gpu/gpu_py_platform.c @@ -0,0 +1,81 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bpygpu + * + * - Use ``bpygpu_`` for local API. + * - Use ``BPyGPU`` for public API. + */ + +#include <Python.h> + +#include "BLI_utildefines.h" + +#include "GPU_platform.h" + +#include "gpu_py_platform.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name Functions + * \{ */ + +static PyObject *pygpu_platform_vendor_get(PyObject *UNUSED(self), PyObject *value) +{ + return PyUnicode_FromString(GPU_platform_vendor()); +} + +static PyObject *pygpu_platform_renderer_get(PyObject *UNUSED(self), PyObject *value) +{ + return PyUnicode_FromString(GPU_platform_renderer()); +} + +static PyObject *pygpu_platform_version_get(PyObject *UNUSED(self), PyObject *value) +{ + return PyUnicode_FromString(GPU_platform_version()); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Module + * \{ */ + +static struct PyMethodDef pygpu_platform__tp_methods[] = { + {"vendor_get", (PyCFunction)pygpu_platform_vendor_get, METH_NOARGS, NULL}, + {"renderer_get", (PyCFunction)pygpu_platform_renderer_get, METH_NOARGS, NULL}, + {"version_get", (PyCFunction)pygpu_platform_version_get, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL}, +}; + +PyDoc_STRVAR(pygpu_platform__tp_doc, "This module provides access to GPU Platform definitions."); +static PyModuleDef pygpu_platform_module_def = { + PyModuleDef_HEAD_INIT, + .m_name = "gpu.platform", + .m_doc = pygpu_platform__tp_doc, + .m_methods = pygpu_platform__tp_methods, +}; + +PyObject *bpygpu_platform_init(void) +{ + PyObject *submodule; + + submodule = PyModule_Create(&pygpu_platform_module_def); + + return submodule; +} + +/** \} */ diff --git a/source/blender/python/gpu/gpu_py_platform.h b/source/blender/python/gpu/gpu_py_platform.h new file mode 100644 index 00000000000..19e3e41fb49 --- /dev/null +++ b/source/blender/python/gpu/gpu_py_platform.h @@ -0,0 +1,23 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bpygpu + */ + +#pragma once + +PyObject *bpygpu_platform_init(void); |