Open4

gl4esでテクスチャが入れ変わる問題?

okuokuokuoku

ぜんぜんわからん。。これはマジで解ける気がしない。。

今のところ2つ問題がある:

  1. glBlitFramebuffer が動作していない問題。これは gl4es が指定しているテクスチャ 5 が描画先のときは正しいのに 描画元の時には 1x1 テクスチャになってしまう 問題。
  2. WineD3Dが異なるテクスチャを1つのテクスチャ名で呼んでくる問題。ピクセルシェーダのパラメタと文字テクスチャが1つの番号で呼ばれている。それぞれのテクスチャはサイズも異なるものの前者のテクスチャアップロードが観測されたことは無い。

前者の方はワークアラウンドできるのでワークアラウンドしてしまっているが、後者の問題と現象自体は似てなくもないのでちゃんとデバッグするべきか。。?

prev

https://zenn.dev/okuoku/scraps/703effddfe6e01

okuokuokuoku

1x1のテクスチャがbindされている

RenderDocでは、 glBlitFramebuffer が生成した描画では1x1のテクスチャがbindされているように見える。

そもそもテクスチャがbindされていない状態で描画するとGPUクラッシュになるので、ここはANGLEが親切心で適当なテクスチャをbindしてくれているのではないか。

しかし、描画に使うProgramのUniformには正常にゼロが設定されているし、テクスチャユニットの0番にはちゃんと事前にテクスチャ 5がbindされていることは確認できる。

シェーダの中身も正しそう。

#version 100                  
uniform sampler2D uTex;                                
varying mediump vec2 vTexCoord;                        
void main(){                                           
gl_FragColor = texture2D(uTex, vTexCoord);             
}                                                      

glUniform1iuTex に0番を設定する際は、実際のUniformオブジェクトへの設定はスキップされている。これはANGLEのVulkanバックエンドの仕様らしい。

https://github.com/google/angle/blob/251ba5cb119ff2fed0e861cbc9b096c45004c1fa/src/libANGLE/renderer/vulkan/ProgramVk.cpp#L534-L546

実際の更新は updateSamplerUniform だけで行われる。が、ココでも特に処理を行わずにreturnしている。(0番から0番への変更であるため)

https://github.com/google/angle/blob/251ba5cb119ff2fed0e861cbc9b096c45004c1fa/src/libANGLE/Program.cpp#L4980-L4983

で、最終的にVulkan側のデスクリプタは updateExecutableActiveTexturesForShader で適用され、ここでは確かに 1x1のテクスチャが使われている 。 ...どこで化けたんだ。。

で、この 1x1 のテクスチャは ContextVk::updateActiveTexturesisIncompleteTexture が真になることで生成されているようだ。

しかし glBindTexture で参照できているテクスチャは正しい。

実はOpenGL的なステート変更の順序に何か作法がある。。?UseProgramを先にやらないといけない的な。。

okuokuokuoku

MipMap completeness っぽい

これエラーにならないのか。。

TextureState::computeMipmapCompleteness() が偽を返却している。

GL_TEXTURE_MIN_FILTER を設定すると絵が出るようになった。これ自体はBlitのエミュレーションにおける考慮漏れなのでもうちょっと真面目に修正する必要がある。

blit.c
@@ -379,6 +383,11 @@ void gl4es_blitTexture(GLuint texture,
     if(glstate->actual_tex2d[0] != texture)
         gles_glBindTexture(GL_TEXTURE_2D, texture);

+    // FIXME: On framebuffer blitting, we have to disable filtering since
+    //        Framebuffer texture do not have MipMaps
+    LOAD_GLES(glTexParameteri);
+    gles_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
     if(hardext.esversion==1) {
         if(!IS_TEX2D(tmp))
             gles_glEnable(GL_TEXTURE_2D);
okuokuokuoku

何故か後者の問題も治った

意味わかんねぇ。。

まぁとりあえず治ったから良いか。。