mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
remove readback hacks, allows to read/write guest memory directly
This commit is contained in:
@@ -9025,14 +9025,6 @@ void CheckBufferCacheRangeMerge() {
|
||||
3) &&
|
||||
!CanMergeBufferCacheQueueMask(0, 64),
|
||||
"cross-queue or invalid queue ownership was accepted");
|
||||
Require("BufferCacheRangeMerge", "readback queue ownership",
|
||||
!CanReadbackBufferCacheQueueMask(0, 3) &&
|
||||
CanReadbackBufferCacheQueueMask(uint64_t{1} << 3u, 3) &&
|
||||
!CanReadbackBufferCacheQueueMask((uint64_t{1} << 2u) |
|
||||
(uint64_t{1} << 3u),
|
||||
3) &&
|
||||
!CanReadbackBufferCacheQueueMask(uint64_t{1} << 3u, 64),
|
||||
"zero, cross-queue, or invalid readback ownership was accepted");
|
||||
std::printf("[host] %-32s ok\n", "BufferCacheRangeMerge");
|
||||
}
|
||||
|
||||
@@ -9855,10 +9847,13 @@ void CheckStorageTextureGpuOwnedRebindState() {
|
||||
tracker.ForEachUploadRange(base, size, true,
|
||||
[](uint64_t, uint64_t) noexcept {}, []() noexcept {});
|
||||
uint64_t readable = 0;
|
||||
uint64_t mapped = 0;
|
||||
MEMORY_BASIC_INFORMATION protection{};
|
||||
Require("StorageTextureGpuOwnedRebind", "owned",
|
||||
tracker.IsRegionGpuModified(base, size) && page_manager.IsMapped(base, size) &&
|
||||
(!HostMemoryQueryReadable(base, size, &readable) || readable < size) &&
|
||||
HostMemoryQueryRange(base, size, HostMemoryAccess::Mapped, &mapped) &&
|
||||
mapped == size &&
|
||||
VirtualQuery(memory, &protection, sizeof(protection)) != 0 &&
|
||||
protection.Protect == PAGE_NOACCESS,
|
||||
"GPU-owned storage pages remained host-readable or lost tracker identity");
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "graphics/shader/recompiler/ResourceMaterialization.h"
|
||||
#include "graphics/shader/recompiler/ShaderIR.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
@@ -53,22 +52,7 @@ std::shared_ptr<const Libs::Graphics::ShaderRecompiler::IR::Program> UnbasedFlat
|
||||
return std::make_shared<const Program>(std::move(program));
|
||||
}
|
||||
|
||||
void TestFailurePreservesPriorStage() {
|
||||
using namespace Libs::Graphics;
|
||||
auto cached_program = SrtProgram(0x1001);
|
||||
auto prior_program = std::make_shared<const ShaderRecompiler::IR::Program>();
|
||||
auto prior_resources = std::make_shared<const ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
ShaderStageRuntime stage {prior_program, prior_resources};
|
||||
const std::array<uint32_t, 1> user_data = {};
|
||||
std::string error;
|
||||
Check(!ShaderMaterializeStageRuntime(cached_program, user_data, 0, &stage, &error) &&
|
||||
error.find("failed at 0x0000000000001000") != std::string::npos,
|
||||
"unmapped cache ReadConst did not fail through the checked production reader");
|
||||
Check(stage.program == prior_program && stage.resources == prior_resources,
|
||||
"failed cache rematerialization replaced the prior stage snapshot");
|
||||
}
|
||||
|
||||
void TestMappedSrtUsesCheckedReaderByDefault() {
|
||||
void TestMappedSrtUsesDirectReaderByDefault() {
|
||||
using namespace Libs::Graphics;
|
||||
const uint32_t dword = 0x12345678;
|
||||
auto cached_program = SrtProgram(reinterpret_cast<uint64_t>(&dword));
|
||||
@@ -79,7 +63,7 @@ void TestMappedSrtUsesCheckedReaderByDefault() {
|
||||
"cache rematerialization did not publish the mapped stage");
|
||||
Check(stage.resources->flattened_srt.size() == 1 &&
|
||||
stage.resources->flattened_srt[0] == dword,
|
||||
"cache rematerialization did not use the checked reader by default");
|
||||
"cache rematerialization did not use the direct reader by default");
|
||||
}
|
||||
|
||||
void TestUnbasedFlatCacheHitFailsClosed() {
|
||||
@@ -99,8 +83,7 @@ void TestUnbasedFlatCacheHitFailsClosed() {
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
TestFailurePreservesPriorStage();
|
||||
TestMappedSrtUsesCheckedReaderByDefault();
|
||||
TestMappedSrtUsesDirectReaderByDefault();
|
||||
TestUnbasedFlatCacheHitFailsClosed();
|
||||
std::puts("ShaderStageRuntimeTests: all cases passed");
|
||||
return 0;
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
#include "graphics/shader/shaderVertexMetadata.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace Libs::Graphics;
|
||||
@@ -60,7 +47,7 @@ void CheckRejected(const ShaderMappedData& data, const char* text) {
|
||||
"metadata rejection changed the prior output");
|
||||
}
|
||||
|
||||
void TestValidAndHostileMetadata() {
|
||||
void TestValidAndInvalidMetadata() {
|
||||
Fixture fixture;
|
||||
ShaderVertexMetadata output;
|
||||
std::string error;
|
||||
@@ -70,9 +57,13 @@ void TestValidAndHostileMetadata() {
|
||||
output.input_semantics_count == 1,
|
||||
"valid AGC vertex metadata was decoded incorrectly");
|
||||
|
||||
auto unreadable = fixture.mapped;
|
||||
unreadable.user_data = reinterpret_cast<ShaderUserData*>(uintptr_t {1});
|
||||
CheckRejected(unreadable, "unreadable AGC user-data header was accepted");
|
||||
auto missing_header = fixture.mapped;
|
||||
missing_header.user_data = nullptr;
|
||||
CheckRejected(missing_header, "missing AGC user-data header was accepted");
|
||||
|
||||
Fixture missing_offsets;
|
||||
missing_offsets.user_data.direct_resource_offset = nullptr;
|
||||
CheckRejected(missing_offsets.mapped, "missing direct-resource offsets were accepted");
|
||||
|
||||
Fixture excessive_resources;
|
||||
excessive_resources.user_data.direct_resource_count =
|
||||
@@ -88,65 +79,15 @@ void TestValidAndHostileMetadata() {
|
||||
static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] = 63;
|
||||
CheckRejected(excessive_register.mapped, "out-of-domain vertex table SGPR was accepted");
|
||||
|
||||
Fixture bad_semantics;
|
||||
bad_semantics.mapped.input_semantics =
|
||||
reinterpret_cast<ShaderSemantic*>(uintptr_t {1});
|
||||
CheckRejected(bad_semantics.mapped, "unreadable vertex semantic array was accepted");
|
||||
}
|
||||
|
||||
void TestCrossPageMetadata() {
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
SYSTEM_INFO system_info {};
|
||||
GetSystemInfo(&system_info);
|
||||
const auto page_size = static_cast<uint64_t>(system_info.dwPageSize);
|
||||
auto* pages = static_cast<uint8_t*>(
|
||||
VirtualAlloc(nullptr, page_size * 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
|
||||
Check(pages != nullptr, "failed to allocate metadata test pages");
|
||||
DWORD old_protect = 0;
|
||||
Check(VirtualProtect(pages + page_size, page_size, PAGE_NOACCESS, &old_protect) != 0,
|
||||
"failed to protect metadata test page");
|
||||
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||
const auto native_page_size = sysconf(_SC_PAGESIZE);
|
||||
Check(native_page_size > 0, "failed to query page size");
|
||||
const auto page_size = static_cast<uint64_t>(native_page_size);
|
||||
auto* pages = static_cast<uint8_t*>(
|
||||
mmap(nullptr, page_size * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
Check(pages != MAP_FAILED, "failed to allocate metadata test pages");
|
||||
Check(mprotect(pages + page_size, page_size, PROT_NONE) == 0,
|
||||
"failed to protect metadata test page");
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
Fixture fixture;
|
||||
auto header_crossing = fixture.mapped;
|
||||
header_crossing.user_data = reinterpret_cast<ShaderUserData*>(
|
||||
pages + page_size - sizeof(ShaderUserData) + 1);
|
||||
CheckRejected(header_crossing, "cross-page AGC user-data header was accepted");
|
||||
|
||||
auto offsets_crossing = fixture.mapped;
|
||||
fixture.user_data.direct_resource_offset =
|
||||
reinterpret_cast<uint16_t*>(pages + page_size - sizeof(uint16_t));
|
||||
CheckRejected(offsets_crossing, "cross-page direct-resource offsets were accepted");
|
||||
|
||||
fixture.user_data.direct_resource_offset = fixture.offsets.data();
|
||||
auto semantics_crossing = fixture.mapped;
|
||||
semantics_crossing.input_semantics =
|
||||
reinterpret_cast<ShaderSemantic*>(pages + page_size - sizeof(uint16_t));
|
||||
CheckRejected(semantics_crossing, "cross-page vertex semantics were accepted");
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
Check(VirtualFree(pages, 0, MEM_RELEASE) != 0, "failed to free metadata test pages");
|
||||
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||
Check(munmap(pages, page_size * 2) == 0, "failed to free metadata test pages");
|
||||
#endif
|
||||
Fixture missing_semantics;
|
||||
missing_semantics.mapped.input_semantics = nullptr;
|
||||
CheckRejected(missing_semantics.mapped, "missing vertex semantic array was accepted");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
TestValidAndHostileMetadata();
|
||||
TestCrossPageMetadata();
|
||||
TestValidAndInvalidMetadata();
|
||||
std::puts("ShaderVertexMetadataTests: all cases passed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user