Hide menu pictures only inside the menu frames
The hidden-texture list stayed active in a game; a game texture made at the address of a freed menu picture was skipped (rendering glitches in-game). Hiding now applies only while the main menu's frame or the in-game options draw over the menu background. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
db87e276bf
commit
c4aacbcdd2
2 files changed
+20
-4
No files matched your search
+17
-2
@@ -409,10 +409,22 @@ DrawPrimitiveFn g_drawPrimitive = nullptr;
|
|||||||
DrawIndexedPrimitiveFn g_drawIndexedPrimitive = nullptr;
|
DrawIndexedPrimitiveFn g_drawIndexedPrimitive = nullptr;
|
||||||
|
|
||||||
// Textures not drawn (SetHiddenTextures): the surface bound to stage 0 is
|
// Textures not drawn (SetHiddenTextures): the surface bound to stage 0 is
|
||||||
// tracked per thread (each thread draws with its own device calls).
|
// tracked per thread (each thread draws with its own device calls). Only
|
||||||
|
// inside a frame drawn over the menu background (g_hidingPictures: the main
|
||||||
|
// menu's, the options' in a game): the list keeps surfaces the cache may
|
||||||
|
// have freed since, and a game texture made at the same address was skipped
|
||||||
|
// in the world view (user, 2026-10-21: "rendering glitches ingame").
|
||||||
constexpr int kHiddenTextureMax = 64;
|
constexpr int kHiddenTextureMax = 64;
|
||||||
std::atomic<void*> g_hiddenTextures[kHiddenTextureMax] = {};
|
std::atomic<void*> g_hiddenTextures[kHiddenTextureMax] = {};
|
||||||
thread_local void* g_boundTexture = nullptr;
|
thread_local void* g_boundTexture = nullptr;
|
||||||
|
thread_local int g_hidingPictures = 0;
|
||||||
|
|
||||||
|
struct HidingPictures {
|
||||||
|
HidingPictures() { ++g_hidingPictures; }
|
||||||
|
~HidingPictures() { --g_hidingPictures; }
|
||||||
|
HidingPictures(const HidingPictures&) = delete;
|
||||||
|
HidingPictures& operator=(const HidingPictures&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
using SetTextureFn = HRESULT(__stdcall*)(void* device, DWORD stage, void* surface);
|
using SetTextureFn = HRESULT(__stdcall*)(void* device, DWORD stage, void* surface);
|
||||||
SetTextureFn g_setTexture = nullptr;
|
SetTextureFn g_setTexture = nullptr;
|
||||||
@@ -425,7 +437,7 @@ HRESULT __stdcall SetTextureTracked(void* device, DWORD stage, void* surface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BoundTextureHidden() {
|
bool BoundTextureHidden() {
|
||||||
if (!g_boundTexture) {
|
if (!g_boundTexture || g_hidingPictures == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const auto& hidden : g_hiddenTextures) {
|
for (const auto& hidden : g_hiddenTextures) {
|
||||||
@@ -521,9 +533,11 @@ public:
|
|||||||
Viewport7 frame = {static_cast<DWORD>(dx), 0, kLayoutWidth, 768, previous_.minZ, previous_.maxZ};
|
Viewport7 frame = {static_cast<DWORD>(dx), 0, kLayoutWidth, 768, previous_.minZ, previous_.maxZ};
|
||||||
device_ = device;
|
device_ = device;
|
||||||
g_setViewport(device, &frame);
|
g_setViewport(device, &frame);
|
||||||
|
++g_hidingPictures;
|
||||||
}
|
}
|
||||||
~FrameScope() {
|
~FrameScope() {
|
||||||
if (device_) {
|
if (device_) {
|
||||||
|
--g_hidingPictures;
|
||||||
g_setViewport(device_, &previous_);
|
g_setViewport(device_, &previous_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -872,6 +886,7 @@ int RenderMenuFrame(void* device, bool framed, int (*body)(void* context), void*
|
|||||||
const int width = mods::widescreen::RenderWidth();
|
const int width = mods::widescreen::RenderWidth();
|
||||||
const int dx = framed && width > kLayoutWidth ? (width - kLayoutWidth) / 2 : 0;
|
const int dx = framed && width > kLayoutWidth ? (width - kLayoutWidth) / 2 : 0;
|
||||||
g_menuFrameDx = dx;
|
g_menuFrameDx = dx;
|
||||||
|
HidingPictures hiding;
|
||||||
Viewport7 previous;
|
Viewport7 previous;
|
||||||
auto getViewport =
|
auto getViewport =
|
||||||
device ? reinterpret_cast<GetViewportFn>((*static_cast<void***>(device))[kVtableGetViewport]) : nullptr;
|
device ? reinterpret_cast<GetViewportFn>((*static_cast<void***>(device))[kVtableGetViewport]) : nullptr;
|
||||||
|
|||||||
+3
-2
@@ -48,8 +48,9 @@ int HandleCanvas(void* event, int (*body)(void* context), void* context);
|
|||||||
int RenderMenuFrame(void* device, bool framed, int (*body)(void* context), void* context);
|
int RenderMenuFrame(void* device, bool framed, int (*body)(void* context), void* context);
|
||||||
int MenuFrameOffsetX();
|
int MenuFrameOffsetX();
|
||||||
|
|
||||||
// Quads drawn with one of these textures (Direct3D surfaces) are left out,
|
// Quads drawn with one of these textures (Direct3D surfaces) are left out
|
||||||
// on every thread, until the list changes (at most 64).
|
// inside the frames drawn over the menu background (RenderMenuFrame, the
|
||||||
|
// in-game options), until the list changes (at most 64).
|
||||||
void SetHiddenTextures(void* const* surfaces, int count);
|
void SetHiddenTextures(void* const* surfaces, int count);
|
||||||
|
|
||||||
} // namespace mods::hud
|
} // namespace mods::hud
|
||||||
Reference in new issue
Block a user