Open furudbat opened 4 months ago
For Context, LoadModelFromMesh
from rmodels.c
:
// Load model from generated mesh
// WARNING: A shallow copy of mesh is generated, passed by value,
// as long as struct contains pointers to data and some values, we get a copy
// of mesh pointing to same data as original version... be careful!
Model LoadModelFromMesh(Mesh mesh)
{
Model model = { 0 };
model.transform = MatrixIdentity();
model.meshCount = 1;
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
model.meshes[0] = mesh; ///< here
Seems like the mesh
ownership is shared with the model.
Good catch :+1: What would be the best way around this? Something similar to the TextureUnmanaged approach we took?
~~I'm honestly not sure, my first though would be a Mesh
and SharedMesh
class, the SharedMesh
can only been used by the Model
. (Maybe something like a shared_ptr
), but idk.
The SharedMesh
has a "weak-ptr" to the Model(s) and know when the Model has been unloaded, so it didn't need to unload (itself). (but that's just to much shared memory management :skull: IMO)~~
Maybe a MeshUnmanaged
can be fine for the first solution.
I also had look into RenderTexture
and they have similar ownership problem, I changed my own code to this:
void SetTexture(const ::Texture& newTexture) = delete;
void SetTexture(::Texture&& newTexture) {
texture = newTexture;
newTexture = NullTexture;
}
rtextures.c
// Unload render texture from GPU memory (VRAM)
void UnloadRenderTexture(RenderTexture2D target)
{
if (target.id > 0)
{
if (target.texture.id > 0)
{
// Color texture attached to FBO is deleted
rlUnloadTexture(target.texture.id);
}
// NOTE: Depth texture/renderbuffer is automatically
// queried and deleted before deleting framebuffer
rlUnloadFramebuffer(target.id);
}
}
texture
in RenderTexture
gets unloaded.
Hello, I noticed this could happen with Shaders as well, as seen in Raylib's rmodels.c:2110
:
// Unload material from memory
void UnloadMaterial(Material material)
{
// Unload material shader (avoid unloading default shader, managed by raylib)
if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);
...
I suppose a ShaderUnamanged class may also be required.
Good catch, @DenisBelmondo! Let's re-work this issue for Shaders too.
https://github.com/RobLoach/raylib-cpp/blob/master/include/Material.hpp#L54
GETTERSETTER(::Shader, Shader, shader)
GETTERSETTER(::MaterialMap*, Maps, maps)
// TODO(RobLoach): Resolve the Material params being a float[4].
// GETTERSETTER(float[4], Params, params)
Seem like the getter for shader
needs to return ShaderUnamanged
OR just an and the setter needs to move the ownership of ::Shader*
(?, keep in mind the owner is still the Material
, so beware of dangling-pointer...)Shader&&
(or Owner<::Shader>&&
) into the Material.
void SetShader(const Shader&) = delete;
void SetShader(::Shader*) { ... } // keep the old API ?, risk of dangling pointer, who is the owner of this pointer ???
//void SetShader(const ShaderUnamanged&) = delete; // not sure about setter for ShaderUnamanged
void SetShader(Shader&&) { ... }
void SetShader(::Shader&&) { ... }
I guess you load the Shader via raylib (C API) or use the Shader
class and move it into the Material:
raylib::Material mat;
{
raylib::Shader shr (...);
mat.SetShader(shr);
}
{
mat.SetShader(LoadShader(...))
}
EDIT:
@RobLoach void SetShader(::Shader*) = delete
This can to be a Breaking Change for the Shader class
https://github.com/RobLoach/raylib-cpp/blob/master/include/Material.hpp#L75
Maybe when resetting the shader
in Material
, the id
should be set to rlGetShaderIdDefault()
and shader.locs = nullptr;
(just to be safe).
When loading the Models with Mesh the ownership is not clear and the mash(es)(?) got double freed.
Logs
models example
rmodel.c