mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Fix] (Tessellation): compare the default patch levels by bit pattern, so a NaN level stops re-linking the program on every draw
This commit is contained in:
@@ -220,8 +220,13 @@ namespace MobileGL {
|
||||
// BumpVersions(), not just ++m_version, for the same reason SetPatchVertices does it:
|
||||
// these levels are compiled INTO the synthesized pass-through tessellation control
|
||||
// stage on both backends, so changing one makes an already-built program stale.
|
||||
//
|
||||
// The redundant-write guard compares BIT PATTERNS, not floats: glPatchParameterfv
|
||||
// accepts NaN, and a float compare would let a re-set of the identical NaN tuple fall
|
||||
// through and bump the pipeline-state version - invalidating DirectVulkan's pipeline
|
||||
// memo and DirectGLES's render-state span - on every single call.
|
||||
void RenderState::SetPatchDefaultOuterLevel(const FloatVec4& levels) {
|
||||
if (m_parameters.PatchDefaultOuterLevel == levels) return;
|
||||
if (BitwiseEqual(m_parameters.PatchDefaultOuterLevel, levels)) return;
|
||||
|
||||
m_parameters.PatchDefaultOuterLevel = levels;
|
||||
BumpVersions();
|
||||
@@ -232,7 +237,7 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void RenderState::SetPatchDefaultInnerLevel(const FloatVec2& levels) {
|
||||
if (m_parameters.PatchDefaultInnerLevel == levels) return;
|
||||
if (BitwiseEqual(m_parameters.PatchDefaultInnerLevel, levels)) return;
|
||||
|
||||
m_parameters.PatchDefaultInnerLevel = levels;
|
||||
BumpVersions();
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <Includes.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace MobileGL {
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
struct VecBase {
|
||||
@@ -84,6 +86,16 @@ namespace MobileGL {
|
||||
}
|
||||
};
|
||||
|
||||
// Bit-pattern equality, for a vector used as a cache or staleness KEY rather than as a
|
||||
// number. IEEE `==` - which operator== above is - says a NaN never equals itself, so a single
|
||||
// NaN component makes every comparison answer "changed" and whatever the key guards is
|
||||
// rebuilt on every use, forever. Two zeros of opposite sign compare unequal here, which only
|
||||
// ever costs one extra rebuild.
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
Bool BitwiseEqual(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b) {
|
||||
return std::memcmp(a.data.data(), b.data.data(), sizeof(T) * N) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct Vec2 : public VecBase<Vec2<T>, T, 2> {
|
||||
using Base = VecBase<Vec2<T>, T, 2>;
|
||||
|
||||
Reference in New Issue
Block a user