mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-16 06:23:23 +09:00
[MG_Backend, MG_Test] (P7): a PH-5 unit control that discriminates the element charge, @Ph-declined on PH-2's eight Fatal sites, and the mip-shadow comment made true
This commit is contained in:
@@ -3012,7 +3012,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// stops being twinned is the failure mode the refusal exists to replace.
|
||||
if (res.Slot >= BackendBufferResourceTable::kMaxHandleSlot) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.HandleSlot\"} - "
|
||||
"buffer twin request named slot %u, past this table's %u bound",
|
||||
@@ -3027,7 +3027,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const Uint32 liveGen = g_backendBufferResources.LiveGenAt(res.Slot);
|
||||
if (liveGen != 0 && liveGen > res.Gen) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.Generation\"} - "
|
||||
"buffer twin request named generation %u at slot %u, behind live generation %u",
|
||||
@@ -4348,7 +4348,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (MG_Pipe::MGPipeHandleIsNull(handle)) return false;
|
||||
if (handle.Slot >= Registry::SlotTable::kMaxHandleSlot) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.HandleSlot\"} - "
|
||||
"%s handle slot %u is past this table's %u bound",
|
||||
@@ -4363,7 +4363,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const Uint32 liveGen = registry.LiveGenAt(handle.Slot);
|
||||
if (liveGen != 0 && liveGen > handle.Gen) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.Generation\"} - "
|
||||
"%s handle {%u, %u} names generation behind live generation %u",
|
||||
|
||||
@@ -481,7 +481,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (MG_Pipe::MGPipeHandleIsNull(handle)) return nullptr;
|
||||
if (handle.Slot >= SlotTable::kMaxHandleSlot) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.HandleSlot\"} - "
|
||||
"GetOrCreateByHandle named slot %u, past this table's %u bound",
|
||||
@@ -493,7 +493,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const Uint32 liveGen = m_slotTable.LiveGenAt(handle.Slot);
|
||||
if (liveGen != 0 && liveGen > handle.Gen) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.Generation\"} - "
|
||||
"GetOrCreateByHandle named generation %u at slot %u, behind live generation %u",
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// PH-2: handle.Slot is peer supplied on the disaggregated arm. Release builds
|
||||
// must publish a named protocol fault instead of silently returning m_nullTwin.
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.HandleSlot\"} - "
|
||||
"GetOrCreate(handle) named slot %u, past this table's %u bound",
|
||||
@@ -385,7 +385,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// PH-2: a stale peer generation must not silently shed the incumbent twin in a
|
||||
// release server. The funnel names the exact identity fault and notifies the peer.
|
||||
MG_Pipe::MGPipeSessionFail(
|
||||
MG_Pipe::MGPipeSessionFail( // @Ph-declined (ID-P7-1): PH-2 stays Fatal, CONTRACT-P7 §12
|
||||
MG_Pipe::MGPipeFatalFamily::ProtocolCorruption,
|
||||
"MGPipe: Fatal{ProtocolCorruption, \"BackendSlotTable.Generation\"} - "
|
||||
"GetOrCreate(handle) named generation %u at slot %u, behind live generation %u",
|
||||
|
||||
@@ -1692,8 +1692,8 @@ void main() {
|
||||
const Uint64 key = MG_Remote::Server::StagedTextureStore::KeyForTwinAddress(&resource);
|
||||
for (const auto uploadTarget : uploadTargets) {
|
||||
for (Uint32 level = baseMipLevel + 1; level < requiredMipLevelCount; ++level) {
|
||||
// A level the shadow already tracks (an adopted base chain) keeps its bytes;
|
||||
// the generation made the GPU newer than either, which the mark says.
|
||||
// Bytes the shadow held for a generated level go: the declaration below moves its
|
||||
// format and byte bound (NoteLevelDefined clears them); the GPU copy is newer.
|
||||
// PH-4: a twin-address key never receives a staged run (no Adopt names one),
|
||||
// so these generated levels are declared BYTELESS - an Unknown format gives a
|
||||
// zero byte bound and skips the Tex2D device-limit rule the defaults would
|
||||
|
||||
@@ -32,7 +32,15 @@
|
||||
// stays name-for-name identical between the pull and the push trees.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Includes.h"
|
||||
#if MOBILEGL_PIPE_PUSH
|
||||
@@ -351,6 +359,59 @@ TEST(ProgramArtifactsCodec, AVectorCountCannotReservePastTheRemainingArchiveByte
|
||||
#endif
|
||||
}
|
||||
|
||||
// PH-5's DISCRIMINATING control (P7 F2 latch). The case above cannot fail on PH-5's account: its
|
||||
// count is one element past PH-5's bound, and with TakeCount put back to the old one-byte-per-
|
||||
// element charge the same count is admitted, resize() is tiny, and the element reads run out of
|
||||
// bytes - DecodeProgramArtifacts answers false either way (red-once: it stays green). What PH-5
|
||||
// actually changed is the ALLOCATION a count may cause before the reads, so this case forges the
|
||||
// count BETWEEN the two bounds - `count == Remaining()`, in an archive padded to 7 MiB - and
|
||||
// decodes it in a forked child whose address space has 64 MiB of headroom. PH-5 refuses before
|
||||
// the resize and the child exits 0; the old bound resizes to Remaining() elements of
|
||||
// sizeof(UniformReflection) each, far past the headroom, and the child dies of std::bad_alloc.
|
||||
// The same shape crosses the wire in PeerLatchTest's D11ArchiveVectorCount row.
|
||||
#if MOBILEGL_PIPE_PUSH && !defined(_WIN32)
|
||||
namespace {
|
||||
[[noreturn]] void DecodeACountOnlyTheByteBoundAdmitsUnderACapAndExit() {
|
||||
Vector<Uint8> bytes;
|
||||
EncodeProgramArtifacts(LinkArtifacts{}, SpirvArtifacts{}, bytes);
|
||||
constexpr SizeT countOffset = sizeof(Uint32) + sizeof(Uint64);
|
||||
bytes.resize(SizeT{7} << 20, 0);
|
||||
const Uint64 remaining = bytes.size() - countOffset - sizeof(Uint64);
|
||||
std::memcpy(bytes.data() + countOffset, &remaining, sizeof(remaining));
|
||||
constexpr Uint64 kHeadroom = Uint64{64} << 20;
|
||||
if (remaining * sizeof(UniformReflection) < 4 * kHeadroom) ::_exit(64); // the case would prove nothing
|
||||
Uint64 vmKb = 0;
|
||||
{
|
||||
std::ifstream status("/proc/self/status");
|
||||
std::string line;
|
||||
while (std::getline(status, line)) {
|
||||
if (line.rfind("VmSize:", 0) == 0) vmKb = std::strtoull(line.c_str() + 7, nullptr, 10);
|
||||
}
|
||||
}
|
||||
if (vmKb == 0) ::_exit(65);
|
||||
rlimit cap{};
|
||||
if (::getrlimit(RLIMIT_AS, &cap) != 0) ::_exit(66);
|
||||
cap.rlim_cur = static_cast<rlim_t>(vmKb * 1024 + kHeadroom);
|
||||
if (::setrlimit(RLIMIT_AS, &cap) != 0) ::_exit(67);
|
||||
LinkArtifacts link;
|
||||
SpirvArtifacts spirv;
|
||||
const Bool decoded = DecodeProgramArtifacts(bytes.data(), bytes.size(), link, spirv);
|
||||
::_exit(!decoded && link.uniformReflection.empty() ? 0 : 3);
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
TEST(ProgramArtifactsCodec, ACountOnlyTheByteBoundAdmitsIsRefusedBeforeItsResize) {
|
||||
#if MOBILEGL_PIPE_PUSH && !defined(_WIN32)
|
||||
EXPECT_EXIT(DecodeACountOnlyTheByteBoundAdmitsUnderACapAndExit(), ::testing::ExitedWithCode(0), ".*")
|
||||
<< "std::bad_alloc escaping the child is the resize PH-5 exists to refuse: the vector count was "
|
||||
"charged one byte per element instead of sizeof(value_type); exit 3 is a decode that did not "
|
||||
"refuse; 64+ is the fixture";
|
||||
#else
|
||||
GTEST_SKIP() << "MOBILEGL_PIPE_PUSH is off (the archive codec is push-only), or no RLIMIT_AS / fork here";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Negative control 2: both the version and schema word must refuse mismatches.
|
||||
// Monolith v1 retains the old native-size echo in that second word.
|
||||
TEST(ProgramArtifactsCodec, AVersionMismatchIsRefused) {
|
||||
|
||||
Reference in New Issue
Block a user