DH API does not notify of texture change

Binding textures returned by the DH API as usual* results in broken code. (usual* = how you'ld usually do it in MC modding)
DhApiResult<Integer> depthId = DhApi.Delayed.renderProxy.getDhDepthTextureId();
if(depthId.success) {
RenderSystem.activeTexture(GL_TEXTURE6);
RenderSystem.bindTexture(depthId.payload);
}
DhApiResult<Integer> depthId = DhApi.Delayed.renderProxy.getDhDepthTextureId();
if(depthId.success) {
RenderSystem.activeTexture(GL_TEXTURE6);
RenderSystem.bindTexture(depthId.payload);
}
The issue here is that DH doesn't use Minecraft's built-in GL State manager RenderSystem (yarn mappings). The problem only becomes apparent when DH reinitializes the LODRenderer. This action will: 1. glDeleteTextures the old texture 2. glGenTextures a new texture 3. On some systems the old and new texture will have the same id (valid by OpenGL Spec) 4. Call RenderSystem.bindTexture with the same texture id. 5. RenderSystemwill not call glBindTexture because it thinks the same old texture is still bound. 6. A deleted texture is now bound to GL_TEXTURE6 I hope my description was clear enough. The DH API does not provide a way to notice this texture change. Probably the only way to circumvent this issue is on my side is to do this:
RenderSystem.bindTexture(depthId.payload);
GL11.glBindTexture(GL_TEXTURE6, depthId.payload);
RenderSystem.bindTexture(depthId.payload);
GL11.glBindTexture(GL_TEXTURE6, depthId.payload);
This will keep MC's state management and the "real" state "in sync", but results in wasted performance and is generally not a nice solution,
9 Replies
BackSun
BackSun•5mo ago
I don't understand your issue. Are you only querying the depth texture once and assuming it will never change?
Wendelin
Wendelin•5mo ago
No, I query it every frame. But when DH initializes a new LODRenderer (when the config is changed f.e.), the new depth texture gets the same OpenGL id as the previous one had[1] (which is permitted by the spec). So when I query it again and call RenderSystem.bindTexture(depthId), the state manger fails to detect that the texture has changed, since the id stayed the same. [1] this is not guaranteed, but it can and does happen. i.e.
void bindTexture(int id) {
if(oldId != id)
GL11.bindTexture(id)
}
void bindTexture(int id) {
if(oldId != id)
GL11.bindTexture(id)
}
The issue is that the id stayed the same, so the new texture is never bound. And there is no way for me to know when the texture changed.
BackSun
BackSun•5mo ago
Why not just use GL11.BindTexture() then? Otherwise I could potentially add events for when the LodRenderer has been created/destroyed.
Wendelin
Wendelin•5mo ago
GL11.BindTexture has two drawbacks: - I still have to bind the texture every frame, even if it is still bound from the previous frame. - RenderSystem won't be aware of the updated binding. Meaning that I also would have to 1) query the previously bound texture 2) bind the depth texture 3) restore the previously bound texture It would be better if I could only bind the texture when it isn't already bound. But since the texture id is not reliable to detect such a change, I can't. I think an event would be the best solution. Alternatively DH could also use RenderSystem (or the underlying GlStateManger), instead of the current solution (GLState.saveState and restore). This would also somewhat improve the performance of DH, because currently, as I see it, GLState.saveState does a bunch of glGet calls every frame, which can be rather slow on some systems. But I'm not sure it would be worth the effort.
BackSun
BackSun•5mo ago
I don't think re-binding the texture every frame is that big of an issue. We have to bind and unbind a number of things every frame to prevent modifying Minecraft's GL state. We are very intentionally not using MC's RenderSystem or GlStateManager since we try to keep our systems as separate from MC as possible. Again, I can look into adding an API event that would fire when the renderer is created/destroyed or when the textures are (re)created.
Wendelin
Wendelin•5mo ago
I have to agree, re-binding the texture every frame is not such a big deal, but still. An event would be much appreciated. If you'll be adding an event, I'ld suggest a ResourceChanged or RenderTargetChanged event, rather than a LodRenderer related one, since that is what's actually of interest. Knowing when the LodRenderer is initialized is not very useful by itself.
BackSun
BackSun•5mo ago
My current plan is something along the lines of Lod Depth/Color Textures Created Event
Wendelin
Wendelin•5mo ago
Yeah, something like that would be great. But does that mean you'll finally have to update the modrinth page 😄?
BackSun
BackSun•5mo ago
Once the next stable build of DH has been released, yes 😉