Merge pull request #3340 from devshahofficial:devshahofficial/mjr-renderer-info

PiperOrigin-RevId: 948183711
Change-Id: I28b256eca22e86ec0ba05a4fa26458d678aca130
This commit is contained in:
Copybara-Service
2026-07-15 01:37:11 -07:00
19 changed files with 225 additions and 3 deletions
+10
View File
@@ -1286,6 +1286,16 @@ This structure specifies the attributes for a single vertex.
.. _mjrRendererInfo:
mjrRendererInfo
~~~~~~~~~~~~~~~
This structure contains information about the available renderer and its current context.
.. mujoco-include:: mjrRendererInfo
.. _mjrContext:
mjrContext
+18
View File
@@ -2797,6 +2797,24 @@ of how to use these functions.
Set default mjrContext.
.. _mjr_defaultRendererInfo:
`mjr_defaultRendererInfo <#mjr_defaultRendererInfo>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mjr_defaultRendererInfo
Set default mjrRendererInfo.
.. _mjr_getRendererInfo:
`mjr_getRendererInfo <#mjr_getRendererInfo>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mjr_getRendererInfo
Get active renderer information.
.. _mjr_makeContext:
`mjr_makeContext <#mjr_makeContext>`__
+6
View File
@@ -1378,6 +1378,10 @@ typedef struct mjrRect_ { // OpenGL rectangle
int width; // width (usually buffer width)
int height; // height (usually buffer height)
} mjrRect;
typedef struct mjrRendererInfo_ { // active renderer identity
const char* renderer; // renderer family: classic, filament, noop
const char* backend; // graphics backend: opengl, vulkan; empty if uninitialized
} mjrRendererInfo;
typedef struct mjrVertexAttribute_ { // vertex attribute format specification
const void* bytes; // vertex data
int usage; // position, normal, etc [mjrVertexAttributeUsage]
@@ -3471,6 +3475,8 @@ void mjv_cameraFrame(mjtNum headpos[3], mjtNum forward[3], mjtNum up[3], mjtNum
void mjv_cameraFrustum(float zver[2], float zhor[2], float zclip[2], const mjModel* m,
const mjvCamera* cam);
void mjr_defaultContext(mjrContext* con);
void mjr_defaultRendererInfo(mjrRendererInfo* info);
void mjr_getRendererInfo(mjrRendererInfo* info);
void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale);
void mjr_changeFont(int fontscale, mjrContext* con);
void mjr_addAux(int index, int width, int height, int samples, mjrContext* con);
+6
View File
@@ -117,6 +117,12 @@ typedef struct mjrRect_ { // OpenGL rectangle
} mjrRect;
typedef struct mjrRendererInfo_ { // active renderer identity
const char* renderer; // renderer family: classic, filament, noop
const char* backend; // graphics backend: opengl, vulkan; empty if uninitialized
} mjrRendererInfo;
typedef struct mjrVertexAttribute_ { // vertex attribute format specification
const void* bytes; // vertex data
int usage; // position, normal, etc [mjrVertexAttributeUsage]
+3
View File
@@ -104,6 +104,9 @@ mjrfContext* mjrf_createContext(const mjrfContextConfig* config);
// Destroys the filament rendering context.
void mjrf_destroyContext(mjrfContext* ctx);
// Gets active renderer information for the given filament context.
void mjrf_getRendererInfo(mjrfContext* ctx, mjrRendererInfo* info);
typedef enum mjrDrawMode_ { // how to draw objects in the scene
mjDRAW_MODE_DEFAULT, // default colors and lighting
mjDRAW_MODE_DEFAULT_NO_TEXTURES, // default, but without textures
+6
View File
@@ -855,6 +855,12 @@ MJAPI void mjv_cameraFrustum(float zver[2], float zhor[2], float zclip[2], cons
// Set default mjrContext.
MJAPI void mjr_defaultContext(mjrContext* con);
// Set default mjrRendererInfo.
MJAPI void mjr_defaultRendererInfo(mjrRendererInfo* info);
// Get active renderer information.
MJAPI void mjr_getRendererInfo(mjrRendererInfo* info);
// Allocate resources in custom OpenGL context; fontscale is mjtFontScale.
MJAPI void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale);
+28
View File
@@ -5480,6 +5480,34 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
doc='Set default mjrContext.',
)),
('mjr_defaultRendererInfo',
FunctionDecl(
name='mjr_defaultRendererInfo',
return_type=ValueType(name='void'),
parameters=(
FunctionParameterDecl(
name='info',
type=PointerType(
inner_type=ValueType(name='mjrRendererInfo'),
),
),
),
doc='Set default mjrRendererInfo.',
)),
('mjr_getRendererInfo',
FunctionDecl(
name='mjr_getRendererInfo',
return_type=ValueType(name='void'),
parameters=(
FunctionParameterDecl(
name='info',
type=PointerType(
inner_type=ValueType(name='mjrRendererInfo'),
),
),
),
doc='Get active renderer information.',
)),
('mjr_makeContext',
FunctionDecl(
name='mjr_makeContext',
+21
View File
@@ -11005,6 +11005,27 @@ STRUCTS: Mapping[str, StructDecl] = dict([
),
),
)),
('mjrRendererInfo',
StructDecl(
name='mjrRendererInfo',
declname='struct mjrRendererInfo_',
fields=(
StructFieldDecl(
name='renderer',
type=PointerType(
inner_type=ValueType(name='char', is_const=True),
),
doc='renderer family: classic, filament, noop',
),
StructFieldDecl(
name='backend',
type=PointerType(
inner_type=ValueType(name='char', is_const=True),
),
doc='graphics backend: opengl, vulkan; empty if uninitialized',
),
),
)),
('mjrVertexAttribute',
StructDecl(
name='mjrVertexAttribute',
+1
View File
@@ -79,6 +79,7 @@ using MjLogMessage = ::mjLogMessage;
// From mjrender.h
using MjrRect = ::mjrRect;
using MjrRendererInfo = ::mjrRendererInfo;
using MjrContext = ::mjrContext;
using MjrVertexAttribute = ::mjrVertexAttribute;
+28 -1
View File
@@ -143,7 +143,6 @@ void MjrContextWrapper::Free() {
// mjr_freeContext is safe to call multiple times.
InterceptMjErrors(mjr_freeContext)(ptr_);
}
} // namespace _impl
namespace {
@@ -241,10 +240,38 @@ PYBIND11_MODULE(_render, pymodule, pybind11::mod_gil_not_used()) {
X(charWidthBig);
#undef X
// ==================== MJRRENDERERINFO ======================================
py::class_<raw::MjrRendererInfo> mjrRendererInfo(pymodule, "MjrRendererInfo");
mjrRendererInfo.def(py::init([]() {
raw::MjrRendererInfo info;
mjr_defaultRendererInfo(&info);
return info;
}));
mjrRendererInfo.def("__copy__", [](const raw::MjrRendererInfo& other) {
return raw::MjrRendererInfo(other);
});
mjrRendererInfo.def("__deepcopy__",
[](const raw::MjrRendererInfo& other, py::dict) {
return raw::MjrRendererInfo(other);
});
DefineStructFunctions(mjrRendererInfo);
mjrRendererInfo.def_property_readonly("renderer",
[](const raw::MjrRendererInfo& info) {
return info.renderer ? info.renderer
: "";
});
mjrRendererInfo.def_property_readonly("backend",
[](const raw::MjrRendererInfo& info) {
return info.backend ? info.backend
: "";
});
using EigenUnsignedCharVectorX = Eigen::Vector<unsigned char, Eigen::Dynamic>;
using EigenFloatVectorX = Eigen::Vector<float, Eigen::Dynamic>;
// Skipped: mjr_defaultContext (have MjrContext.__init__)
Def<traits::mjr_defaultRendererInfo>(pymodule);
Def<traits::mjr_getRendererInfo>(pymodule);
// Skipped: mjr_makeContext (have MjrContext.__init__)
Def<traits::mjr_changeFont>(pymodule);
Def<traits::mjr_addAux>(pymodule);
+7
View File
@@ -28,6 +28,13 @@ import numpy as np
)
class MuJoCoRendererTest(parameterized.TestCase):
def test_renderer_info_binding(self):
info = mujoco.MjrRendererInfo()
mujoco.mjr_getRendererInfo(info)
self.assertIn(info.renderer, ('classic', 'filament', 'noop'))
self.assertIn(info.backend, ('', 'opengl', 'vulkan', 'unknown'))
def test_renderer_unknown_camera_name(self):
xml = """
<mujoco>
+15
View File
@@ -57,6 +57,8 @@ class CompatContext {
scene_bridge_->UploadHeightField(model, id);
}
mjrfContext* Context() const { return context_.get(); }
private:
mjrDrawMode draw_mode_ = mjDRAW_MODE_DEFAULT;
UniquePtr<mjrfContext> context_{nullptr, nullptr};
@@ -189,6 +191,19 @@ void mjr_defaultContext(mjrContext* con) {
memset(con, 0, sizeof(mjrContext));
}
void mjr_defaultRendererInfo(mjrRendererInfo* info) {
memset(info, 0, sizeof(mjrRendererInfo));
info->renderer = "filament";
info->backend = "";
}
void mjr_getRendererInfo(mjrRendererInfo* info) {
mjr_defaultRendererInfo(info);
if (g_context) {
mjrf_getRendererInfo(g_context->Context(), info);
}
}
void mjr_makeFilamentContext(const mjModel* m, const mjrfContextConfig* cfg,
mjrContext* con) {
if (g_context != nullptr) {
+31
View File
@@ -55,6 +55,29 @@ void mjr_defaultContext(mjrContext* con) {
memset(con, 0, sizeof(mjrContext));
}
static int context_count = 0;
static int contextHasResources(const mjrContext* con) {
return con->ntexture || con->offColor || con->offDepthStencil || con->offFBO ||
con->shadowTex || con->shadowFBO || con->rangePlane || con->rangeMesh ||
con->rangeHField || con->rangeBuiltin || con->rangeFont || con->nskin;
}
// set default mjrRendererInfo
void mjr_defaultRendererInfo(mjrRendererInfo* info) {
memset(info, 0, sizeof(mjrRendererInfo));
info->renderer = "classic";
info->backend = "";
}
// get active renderer information
void mjr_getRendererInfo(mjrRendererInfo* info) {
mjr_defaultRendererInfo(info);
if (context_count > 0) {
info->backend = "opengl";
}
}
// allocate lists
@@ -1608,6 +1631,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
// try to bind window (bind offscreen if no window)
mjr_setBuffer(mjFB_WINDOW, con);
context_count++;
return;
}
@@ -1667,6 +1691,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
// set default depth mapping for mjr_readPixels
con->readDepthMap = mjDEPTH_ZERONEAR;
context_count++;
}
@@ -1811,6 +1836,8 @@ void mjr_addAux(int index, int width, int height, int samples, mjrContext* con)
// free resources in custom OpenGL context
void mjr_freeContext(mjrContext* con) {
int had_resources = contextHasResources(con);
// save flags
int glInitialized = con->glInitialized;
int windowAvailable = con->windowAvailable;
@@ -1867,6 +1894,10 @@ void mjr_freeContext(mjrContext* con) {
con->windowSamples = windowSamples;
con->windowStereo = windowStereo;
con->windowDoublebuffer = windowDoublebuffer;
if (had_resources && context_count > 0) {
context_count--;
}
}
+2 -1
View File
@@ -49,6 +49,7 @@ namespace mujoco {
FilamentContext::FilamentContext(const mjrfContextConfig* config)
: config_(*config) {
FilamentPlatformSetup setup = CreateFilamentPlatform(config_);
backend_ = setup.backend;
platform_ = std::move(setup.platform);
filament::Engine::Config engine_config;
@@ -58,7 +59,7 @@ FilamentContext::FilamentContext(const mjrfContextConfig* config)
filament::Engine::Builder engine_builder;
engine_builder.config(&engine_config);
engine_builder.backend(setup.backend);
engine_builder.backend(backend_);
engine_builder.platform(platform_.get());
engine_builder.feature("backend.disable_parallel_shader_compile",
setup.disable_parallel_shader_compile);
@@ -59,6 +59,8 @@ class FilamentContext : public mjrfContext {
filament::Engine* GetEngine() const { return engine_; }
filament::Engine::Backend GetBackend() const { return backend_; }
ObjectManager* GetObjectManager() const { return object_manager_.get(); }
MaterialManager* GetMaterialManager() const {
@@ -76,6 +78,7 @@ class FilamentContext : public mjrfContext {
void ValidateSwapChains(std::span<const mjrfRenderRequest> render_requests);
mjrfContextConfig config_;
filament::Engine::Backend backend_;
filament::Engine* engine_ = nullptr;
filament::Renderer* renderer_ = nullptr;
filament::SwapChain* window_swap_chain_ = nullptr;
+18 -1
View File
@@ -15,9 +15,9 @@
#include <mujoco/mjrfilament.h>
#include <array>
#include <cstdint>
#include <cstring>
#include <filament/Engine.h>
#include <math/mat3.h>
#include <math/vec3.h>
#include <mujoco/mjmodel.h>
@@ -37,6 +37,17 @@ static void setf(float (&arr)[N], const std::array<float, N>& values) {
}
}
static const char* BackendName(filament::Engine::Backend backend) {
switch (backend) {
case filament::Engine::Backend::OPENGL:
return "opengl";
case filament::Engine::Backend::VULKAN:
return "vulkan";
default:
return "unknown";
}
}
extern "C" {
void mjrf_defaultContextConfig(mjrfContextConfig* config) {
@@ -124,6 +135,12 @@ void mjrf_destroyContext(mjrfContext* ctx) {
delete mujoco::FilamentContext::downcast(ctx);
}
void mjrf_getRendererInfo(mjrfContext* ctx, mjrRendererInfo* info) {
memset(info, 0, sizeof(mjrRendererInfo));
info->renderer = "filament";
info->backend = ctx ? BackendName(mujoco::FilamentContext::downcast(ctx)->GetBackend()) : "";
}
mjrfTexture* mjrf_createTexture(mjrfContext* ctx,
const mjrfTextureConfig* config) {
return new mujoco::Texture(
+9
View File
@@ -13,6 +13,7 @@
// limitations under the License.
#include <mujoco/mujoco.h>
#include <string.h>
// This library implements the entirety of mujoco's mjr API as fast-fail stubs.
// You can link this library with your application (instead of standard renderer
@@ -22,6 +23,14 @@
void mjr_defaultContext(mjrContext* con) {
mju_error("mjr_defaultContext not implemented.");
}
void mjr_defaultRendererInfo(mjrRendererInfo* info) {
memset(info, 0, sizeof(mjrRendererInfo));
info->renderer = "noop";
info->backend = "";
}
void mjr_getRendererInfo(mjrRendererInfo* info) {
mjr_defaultRendererInfo(info);
}
void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale) {
mju_error("mjr_makeContext not implemented.");
}
+12
View File
@@ -6182,6 +6182,12 @@ public unsafe struct mjrRect_ {
public int height;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct mjrRendererInfo_ {
public char* renderer;
public char* backend;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct mjrVertexAttribute_ {
public void* bytes;
@@ -7215,6 +7221,12 @@ public static unsafe extern void mjv_cameraFrustum(float* zver, float* zhor, flo
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjr_defaultContext(mjrContext_* con);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjr_defaultRendererInfo(mjrRendererInfo_* info);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjr_getRendererInfo(mjrRendererInfo_* info);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjr_makeContext(mjModel_* m, mjrContext_* con, int fontscale);
+1
View File
@@ -218,6 +218,7 @@ SKIPPED_STRUCTS: tuple[str, ...] = (
"mjUI",
"mjVFS",
"mjrContext",
"mjrRendererInfo",
"mjrRect",
"mjrVertexAttribute",
"mjuiDef",