mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +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:
|
// BumpVersions(), not just ++m_version, for the same reason SetPatchVertices does it:
|
||||||
// these levels are compiled INTO the synthesized pass-through tessellation control
|
// these levels are compiled INTO the synthesized pass-through tessellation control
|
||||||
// stage on both backends, so changing one makes an already-built program stale.
|
// 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) {
|
void RenderState::SetPatchDefaultOuterLevel(const FloatVec4& levels) {
|
||||||
if (m_parameters.PatchDefaultOuterLevel == levels) return;
|
if (BitwiseEqual(m_parameters.PatchDefaultOuterLevel, levels)) return;
|
||||||
|
|
||||||
m_parameters.PatchDefaultOuterLevel = levels;
|
m_parameters.PatchDefaultOuterLevel = levels;
|
||||||
BumpVersions();
|
BumpVersions();
|
||||||
@@ -232,7 +237,7 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderState::SetPatchDefaultInnerLevel(const FloatVec2& levels) {
|
void RenderState::SetPatchDefaultInnerLevel(const FloatVec2& levels) {
|
||||||
if (m_parameters.PatchDefaultInnerLevel == levels) return;
|
if (BitwiseEqual(m_parameters.PatchDefaultInnerLevel, levels)) return;
|
||||||
|
|
||||||
m_parameters.PatchDefaultInnerLevel = levels;
|
m_parameters.PatchDefaultInnerLevel = levels;
|
||||||
BumpVersions();
|
BumpVersions();
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
template <typename Derived, typename T, SizeT N>
|
template <typename Derived, typename T, SizeT N>
|
||||||
struct VecBase {
|
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>
|
template <typename T>
|
||||||
struct Vec2 : public VecBase<Vec2<T>, T, 2> {
|
struct Vec2 : public VecBase<Vec2<T>, T, 2> {
|
||||||
using Base = VecBase<Vec2<T>, T, 2>;
|
using Base = VecBase<Vec2<T>, T, 2>;
|
||||||
|
|||||||
Reference in New Issue
Block a user