Read image descriptors in one bounded span
This commit is contained in:
parent
66f1a82365
commit
d30dca78be
|
|
@ -92,9 +92,9 @@ void PipelineCacheLog(fmt::format_string<Args...> format, Args&&... args) {
|
||||||
Log::WriteToConsoleAndLog(message);
|
Log::WriteToConsoleAndLog(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadShaderGuestMemory(void*, uint64_t address, uint32_t* value) {
|
bool ReadShaderGuestMemory(void*, uint64_t address, std::span<uint32_t> values) {
|
||||||
return value != nullptr &&
|
return !values.empty() &&
|
||||||
Libs::LibKernel::Memory::TryReadGpuCleanBacking(address, value, sizeof(*value));
|
Libs::LibKernel::Memory::TryReadGpuCleanBacking(address, values.data(), values.size_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpShaderSpirv(const char* stage_name, uint64_t shader_hash,
|
void DumpShaderSpirv(const char* stage_name, uint64_t shader_hash,
|
||||||
|
|
|
||||||
|
|
@ -161,28 +161,23 @@ void MarkCleanFlatSlots(const ResourcePlan& program, const DescriptorSource* sou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadSpecializationWord(const SrtRuntime& runtime, uint64_t address, uint32_t& word) {
|
bool ReadScalarTable(uint64_t base, uint64_t size, uint32_t dynamic_offset,
|
||||||
return runtime.read_specialization_memory != nullptr &&
|
const SrtRuntime& runtime, std::span<uint32_t> words) {
|
||||||
runtime.read_specialization_memory(runtime.userdata, address, &word);
|
const auto offset = static_cast<uint64_t>(dynamic_offset) & ~uint64_t {3};
|
||||||
}
|
const auto count = std::min<uint64_t>(words.size(), offset < size ? (size - offset) / 4u : 0u);
|
||||||
|
std::ranges::fill(words.subspan(count), 0u);
|
||||||
bool ReadScalarTableWord(uint64_t base, uint64_t size, uint32_t dynamic_offset,
|
if (count == 0u) {
|
||||||
uint32_t immediate_offset, const SrtRuntime& runtime, uint32_t& word) {
|
|
||||||
const auto byte_offset = static_cast<uint64_t>(dynamic_offset) + immediate_offset;
|
|
||||||
const auto aligned = byte_offset & ~uint64_t {3};
|
|
||||||
if (aligned > size || size - aligned < sizeof(uint32_t)) {
|
|
||||||
word = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
base &= AddressMask & ~uint64_t {3};
|
base &= AddressMask & ~uint64_t {3};
|
||||||
if (aligned > AddressMask - base) {
|
if (offset > AddressMask - base) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto address = base + aligned;
|
const auto address = base + offset;
|
||||||
if (!ReadSpecializationWord(runtime, address, word)) {
|
const auto prefix = words.first(count);
|
||||||
return false;
|
return prefix.size_bytes() - 1u <= AddressMask - address &&
|
||||||
}
|
runtime.read_specialization_memory != nullptr &&
|
||||||
return true;
|
runtime.read_specialization_memory(runtime.userdata, address, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaterializeIndirectImage(const ResourcePlan& program,
|
bool MaterializeIndirectImage(const ResourcePlan& program,
|
||||||
|
|
@ -229,8 +224,8 @@ bool MaterializeIndirectImage(const ResourcePlan& program,
|
||||||
keys.push_back(0u);
|
keys.push_back(0u);
|
||||||
for (uint64_t offset = residue; offset <= limit && probe_count != 0u; offset += step) {
|
for (uint64_t offset = residue; offset <= limit && probe_count != 0u; offset += step) {
|
||||||
uint32_t key = 0;
|
uint32_t key = 0;
|
||||||
if (!ReadScalarTableWord(material.Base48(), material.GetSize(),
|
if (!ReadScalarTable(material.Base48(), material.GetSize(),
|
||||||
static_cast<uint32_t>(offset), 0u, runtime, key)) {
|
static_cast<uint32_t>(offset), runtime, {&key, 1})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
keys.push_back(key);
|
keys.push_back(key);
|
||||||
|
|
@ -252,11 +247,8 @@ bool MaterializeIndirectImage(const ResourcePlan& program,
|
||||||
DescriptorValue candidate;
|
DescriptorValue candidate;
|
||||||
candidate.dword_count = 8u;
|
candidate.dword_count = 8u;
|
||||||
const auto table_offset = (key << 5u) + indirect.table_offset;
|
const auto table_offset = (key << 5u) + indirect.table_offset;
|
||||||
for (uint32_t dword = 0; dword < candidate.dword_count; ++dword) {
|
if (!ReadScalarTable(table_base, table_size, table_offset, runtime, candidate.dwords)) {
|
||||||
if (!ReadScalarTableWord(table_base, table_size, table_offset, dword * sizeof(uint32_t),
|
return false;
|
||||||
runtime, candidate.dwords[dword])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (NullImageDescriptor(candidate) ||
|
if (NullImageDescriptor(candidate) ||
|
||||||
!ValidImageDescriptor(candidate, program.info.images[image_index].r128)) {
|
!ValidImageDescriptor(candidate, program.info.images[image_index].r128)) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||||
SrtRuntime CleanRuntime(SrtRuntime runtime) {
|
SrtRuntime CleanRuntime(SrtRuntime runtime) {
|
||||||
runtime.read_memory = runtime.read_specialization_memory != nullptr
|
runtime.read_memory = runtime.read_specialization_memory != nullptr
|
||||||
? runtime.read_specialization_memory
|
? runtime.read_specialization_memory
|
||||||
: +[](void*, uint64_t, uint32_t*) { return false; };
|
: +[](void*, uint64_t, std::span<uint32_t>) { return false; };
|
||||||
return runtime;
|
return runtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -635,7 +635,7 @@ bool SrtWalker::EvaluateRawRead(const Inst& inst, uint64_t& result) {
|
||||||
}
|
}
|
||||||
uint32_t word = 0;
|
uint32_t word = 0;
|
||||||
if (m_runtime.read_memory != nullptr) {
|
if (m_runtime.read_memory != nullptr) {
|
||||||
if (!m_runtime.read_memory(m_runtime.userdata, address, &word)) {
|
if (!m_runtime.read_memory(m_runtime.userdata, address, {&word, 1})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
using SrtMemoryReader = bool (*)(void* userdata, uint64_t address, uint32_t* value);
|
using SrtMemoryReader = bool (*)(void* userdata, uint64_t address, std::span<uint32_t> values);
|
||||||
|
|
||||||
struct SrtRuntime {
|
struct SrtRuntime {
|
||||||
std::span<const uint32_t> user_data;
|
std::span<const uint32_t> user_data;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ void Check(bool value, const char *text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RejectSpecializationRead(void *userdata, uint64_t, uint32_t *) {
|
bool RejectSpecializationRead(void *userdata, uint64_t, std::span<uint32_t>) {
|
||||||
++*static_cast<uint32_t *>(userdata);
|
++*static_cast<uint32_t *>(userdata);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,14 +138,16 @@ struct TestMemory {
|
||||||
uint32_t fail_after = UINT32_MAX;
|
uint32_t fail_after = UINT32_MAX;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ReadTestMemory(void *userdata, uint64_t address, uint32_t *value) {
|
bool ReadTestMemory(void *userdata, uint64_t address, std::span<uint32_t> values) {
|
||||||
auto *memory = static_cast<TestMemory *>(userdata);
|
auto *memory = static_cast<TestMemory *>(userdata);
|
||||||
if (memory == nullptr || value == nullptr || address < memory->base ||
|
if (memory == nullptr || address < memory->base ||
|
||||||
address - memory->base >= memory->words.size() * sizeof(uint32_t) ||
|
values.size_bytes() > memory->words.size() * sizeof(uint32_t) ||
|
||||||
|
address - memory->base > memory->words.size() * sizeof(uint32_t) - values.size_bytes() ||
|
||||||
memory->reads >= memory->fail_after) {
|
memory->reads >= memory->fail_after) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*value = memory->words[(address - memory->base) / sizeof(uint32_t)];
|
std::copy_n(memory->words.begin() + (address - memory->base) / sizeof(uint32_t),
|
||||||
|
values.size(), values.begin());
|
||||||
memory->reads++;
|
memory->reads++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -156,17 +158,29 @@ struct LinearTestMemory {
|
||||||
uint64_t fail_address = UINT64_MAX;
|
uint64_t fail_address = UINT64_MAX;
|
||||||
uint64_t watched_address = UINT64_MAX;
|
uint64_t watched_address = UINT64_MAX;
|
||||||
uint32_t watched_reads = 0;
|
uint32_t watched_reads = 0;
|
||||||
|
size_t watched_dwords = 0;
|
||||||
|
uint32_t reads = 0;
|
||||||
|
uint32_t descriptor_reads = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ReadLinearTestMemory(void *userdata, uint64_t address, uint32_t *value) {
|
bool ReadLinearTestMemory(void *userdata, uint64_t address, std::span<uint32_t> values) {
|
||||||
auto *memory = static_cast<LinearTestMemory *>(userdata);
|
auto *memory = static_cast<LinearTestMemory *>(userdata);
|
||||||
if (memory == nullptr || value == nullptr || address < memory->base ||
|
if (memory == nullptr || address < memory->base ||
|
||||||
address - memory->base >= memory->words.size() * sizeof(uint32_t) ||
|
values.size_bytes() > memory->words.size() * sizeof(uint32_t) ||
|
||||||
(address & 3u) != 0u || address == memory->fail_address) {
|
address - memory->base > memory->words.size() * sizeof(uint32_t) - values.size_bytes() ||
|
||||||
|
(address & 3u) != 0u ||
|
||||||
|
(memory->fail_address >= address && memory->fail_address - address < values.size_bytes())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*value = memory->words[(address - memory->base) / sizeof(uint32_t)];
|
std::copy_n(memory->words.begin() + (address - memory->base) / sizeof(uint32_t),
|
||||||
if (address == memory->watched_address) ++memory->watched_reads;
|
values.size(), values.begin());
|
||||||
|
++memory->reads;
|
||||||
|
if (values.size() == 8u) ++memory->descriptor_reads;
|
||||||
|
if (memory->watched_address >= address &&
|
||||||
|
memory->watched_address - address < values.size_bytes()) {
|
||||||
|
++memory->watched_reads;
|
||||||
|
memory->watched_dwords = values.size();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,6 +327,22 @@ void TestInvariantIndirectImageMaterialization() {
|
||||||
snapshot.images[0].dwords.begin()),
|
snapshot.images[0].dwords.begin()),
|
||||||
"invariant indirect image table did not materialize");
|
"invariant indirect image table did not materialize");
|
||||||
|
|
||||||
|
user_data[5] = 0u;
|
||||||
|
user_data[6] = 19u;
|
||||||
|
memory.fail_address = 0x2010u;
|
||||||
|
memory.watched_address = 0x2000u;
|
||||||
|
Check(MaterializeResources(resource_plan, runtime, snapshot, specialization) &&
|
||||||
|
memory.watched_dwords == 4u &&
|
||||||
|
std::equal(image_descriptor.begin(), image_descriptor.end(),
|
||||||
|
snapshot.images[0].dwords.begin()),
|
||||||
|
"partial scalar-buffer descriptor read crossed bounds instead of zeroing its tail");
|
||||||
|
memory.fail_address = 0x2008u;
|
||||||
|
Check(!MaterializeResources(resource_plan, runtime, snapshot, specialization),
|
||||||
|
"unreadable memory inside the descriptor prefix was accepted");
|
||||||
|
user_data[5] = 16u << 16u;
|
||||||
|
user_data[6] = 4u;
|
||||||
|
memory.watched_address = UINT64_MAX;
|
||||||
|
|
||||||
memory.fail_address = 0x1004u;
|
memory.fail_address = 0x1004u;
|
||||||
Check(!MaterializeResources(resource_plan, runtime, snapshot,
|
Check(!MaterializeResources(resource_plan, runtime, snapshot,
|
||||||
specialization),
|
specialization),
|
||||||
|
|
@ -609,7 +639,7 @@ void TestGuardedDirectImageTable() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fill_table(memory, table);
|
fill_table(memory, table);
|
||||||
const std::array<uint32_t, 2> user_data{0x1000u, 0u};
|
std::array<uint32_t, 2> user_data{0x1000u, 0u};
|
||||||
SrtRuntime runtime{.user_data = user_data, .read_memory = ReadLinearTestMemory,
|
SrtRuntime runtime{.user_data = user_data, .read_memory = ReadLinearTestMemory,
|
||||||
.userdata = &memory,
|
.userdata = &memory,
|
||||||
.read_specialization_memory = ReadLinearTestMemory};
|
.read_specialization_memory = ReadLinearTestMemory};
|
||||||
|
|
@ -617,7 +647,8 @@ void TestGuardedDirectImageTable() {
|
||||||
ResourceSpecialization specialization;
|
ResourceSpecialization specialization;
|
||||||
Check(MaterializeResources(plan, runtime, snapshot, specialization) &&
|
Check(MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
snapshot.images.size() == 32u && specialization.images.size() == 32u &&
|
snapshot.images.size() == 32u && specialization.images.size() == 32u &&
|
||||||
snapshot.flattened_srt[specialization.images[0].indirect_mapping_offset] == 32u,
|
snapshot.flattened_srt[specialization.images[0].indirect_mapping_offset] == 32u &&
|
||||||
|
memory.reads == 34u && memory.descriptor_reads == 32u,
|
||||||
"direct table did not retain all 32 reachable descriptors");
|
"direct table did not retain all 32 reachable descriptors");
|
||||||
memory.words[(table - memory.base) / 4u + 31u * 8u] = 0x987u;
|
memory.words[(table - memory.base) / 4u + 31u * 8u] = 0x987u;
|
||||||
Check(MaterializeResources(plan, runtime, snapshot, specialization) &&
|
Check(MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
|
|
@ -637,6 +668,20 @@ void TestGuardedDirectImageTable() {
|
||||||
Check(!MaterializeResources(plan, runtime, snapshot, specialization) &&
|
Check(!MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
wrapping.watched_reads == 0u,
|
wrapping.watched_reads == 0u,
|
||||||
"direct table wrapped its descriptor address at the 48-bit boundary");
|
"direct table wrapped its descriptor address at the 48-bit boundary");
|
||||||
|
|
||||||
|
LinearTestMemory endpoint;
|
||||||
|
endpoint.base = (uint64_t{1} << 48u) - 0x1000u;
|
||||||
|
const auto crossing = (uint64_t{1} << 48u) - 16u;
|
||||||
|
endpoint.words[0] = static_cast<uint32_t>(crossing - 344u);
|
||||||
|
endpoint.words[1] = static_cast<uint32_t>((crossing - 344u) >> 32u);
|
||||||
|
fill_table(endpoint, crossing);
|
||||||
|
endpoint.watched_address = crossing;
|
||||||
|
user_data = {static_cast<uint32_t>(endpoint.base),
|
||||||
|
static_cast<uint32_t>(endpoint.base >> 32u)};
|
||||||
|
runtime.userdata = &endpoint;
|
||||||
|
Check(!MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
|
endpoint.watched_reads == 0u,
|
||||||
|
"batched descriptor read crossed the 48-bit endpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestUniformScalarBufferImage() {
|
void TestUniformScalarBufferImage() {
|
||||||
|
|
@ -779,12 +824,12 @@ void TestComputeBufferFill() {
|
||||||
std::array<uint32_t, 4> userdata{0x200000u, 4u << 16, 0x4000u, 0x14204u};
|
std::array<uint32_t, 4> userdata{0x200000u, 4u << 16, 0x4000u, 0x14204u};
|
||||||
ResourceSnapshot snapshot;
|
ResourceSnapshot snapshot;
|
||||||
ResourceSpecialization specialization;
|
ResourceSpecialization specialization;
|
||||||
const auto Read = +[](void *data, uint64_t address, uint32_t *word) {
|
const auto Read = +[](void *data, uint64_t address, std::span<uint32_t> words) {
|
||||||
auto &memory = *static_cast<TestMemory *>(data);
|
auto &memory = *static_cast<TestMemory *>(data);
|
||||||
if (address != memory.base)
|
if (address != memory.base || words.size() != 1u)
|
||||||
return false;
|
return false;
|
||||||
++memory.reads;
|
++memory.reads;
|
||||||
*word = memory.words[0];
|
words[0] = memory.words[0];
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Check(MaterializeResources(
|
Check(MaterializeResources(
|
||||||
|
|
@ -2051,7 +2096,7 @@ void TestConditionalIndirectImageMaterialization() {
|
||||||
uint32_t reads = 0;
|
uint32_t reads = 0;
|
||||||
const SrtRuntime runtime{
|
const SrtRuntime runtime{
|
||||||
.user_data = user_data, .userdata = &reads,
|
.user_data = user_data, .userdata = &reads,
|
||||||
.read_specialization_memory = [](void *data, uint64_t, uint32_t *) {
|
.read_specialization_memory = [](void *data, uint64_t, std::span<uint32_t>) {
|
||||||
++*static_cast<uint32_t *>(data);
|
++*static_cast<uint32_t *>(data);
|
||||||
return false;
|
return false;
|
||||||
}};
|
}};
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,14 @@ struct TestMemory {
|
||||||
uint32_t reads = 0;
|
uint32_t reads = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ReadMemory(void *userdata, uint64_t address, uint32_t *value) {
|
bool ReadMemory(void *userdata, uint64_t address, std::span<uint32_t> values) {
|
||||||
auto &memory = *static_cast<TestMemory *>(userdata);
|
auto &memory = *static_cast<TestMemory *>(userdata);
|
||||||
const auto it = memory.words.find(address);
|
for (auto &value : values) {
|
||||||
if (it == memory.words.end()) {
|
const auto it = memory.words.find(address);
|
||||||
return false;
|
if (it == memory.words.end()) return false;
|
||||||
|
value = it->second;
|
||||||
|
address += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
*value = it->second;
|
|
||||||
memory.reads++;
|
memory.reads++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1240,13 +1240,13 @@ std::array<u32, 64> MakeNativeUserData(const std::array<u32, 64> *source) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadTestMemory(void *userdata, uint64_t address, u32 *value) {
|
bool ReadTestMemory(void *userdata, uint64_t address, std::span<u32> values) {
|
||||||
const auto *data = static_cast<const std::vector<u32> *>(userdata);
|
const auto *data = static_cast<const std::vector<u32> *>(userdata);
|
||||||
if (data == nullptr || value == nullptr || address % 4u != 0 ||
|
if (data == nullptr || address % 4u != 0 || values.size() > data->size() ||
|
||||||
address / 4u >= data->size()) {
|
address / 4u > data->size() - values.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*value = (*data)[address / 4u];
|
std::copy_n(data->begin() + address / 4u, values.size(), values.begin());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12122,9 +12122,9 @@ public:
|
||||||
Require(name, "stencil fill materialization",
|
Require(name, "stencil fill materialization",
|
||||||
ShaderRecompiler::IR::MaterializeResources(stencil_plan,
|
ShaderRecompiler::IR::MaterializeResources(stencil_plan,
|
||||||
{.user_data = stencil_userdata, .userdata = &stencil_byte,
|
{.user_data = stencil_userdata, .userdata = &stencil_byte,
|
||||||
.read_specialization_memory = +[](void *data, uint64_t address, uint32_t *word) {
|
.read_specialization_memory = +[](void *data, uint64_t address, std::span<uint32_t> words) {
|
||||||
if (address != reinterpret_cast<uint64_t>(data)) return false;
|
if (address != reinterpret_cast<uint64_t>(data) || words.size() != 1u) return false;
|
||||||
*word = *static_cast<uint32_t *>(data);
|
words[0] = *static_cast<uint32_t *>(data);
|
||||||
return true;
|
return true;
|
||||||
}}, stencil_snapshot, stencil_specialization),
|
}}, stencil_snapshot, stencil_specialization),
|
||||||
"captured stencil shader could not resolve its clear byte");
|
"captured stencil shader could not resolve its clear byte");
|
||||||
|
|
@ -28001,9 +28001,9 @@ void CheckPs5GameExampleImageClearRuntimeShape() {
|
||||||
.shader_base = reinterpret_cast<uint64_t>(code.data()),
|
.shader_base = reinterpret_cast<uint64_t>(code.data()),
|
||||||
.userdata = &scalar_clear,
|
.userdata = &scalar_clear,
|
||||||
.read_specialization_memory = clean_scalar
|
.read_specialization_memory = clean_scalar
|
||||||
? +[](void *data, uint64_t address, uint32_t *word) {
|
? +[](void *data, uint64_t address, std::span<uint32_t> words) {
|
||||||
if (address != reinterpret_cast<uint64_t>(data)) return false;
|
if (address != reinterpret_cast<uint64_t>(data) || words.size() != 1u) return false;
|
||||||
*word = *static_cast<uint32_t *>(data);
|
words[0] = *static_cast<uint32_t *>(data);
|
||||||
return true;
|
return true;
|
||||||
} : nullptr,
|
} : nullptr,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -107,11 +107,11 @@ ShaderRecompiler::CompileOptions MakeCompileOptions(ShaderType stage) {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadHostTestMemory(void *, uint64_t address, uint32_t *value) {
|
bool ReadHostTestMemory(void *, uint64_t address, std::span<uint32_t> values) {
|
||||||
if (address == 0 || value == nullptr) {
|
if (address == 0 || values.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::memcpy(value, reinterpret_cast<const void *>(address), sizeof(*value));
|
std::memcpy(values.data(), reinterpret_cast<const void *>(address), values.size_bytes());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1425,11 +1425,8 @@ void SetImageTestFormat(std::array<uint32_t, 64> *data, uint32_t srsrc,
|
||||||
(*data)[format_dword] = static_cast<uint32_t>(format) << 20u;
|
(*data)[format_dword] = static_cast<uint32_t>(format) << 20u;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadZeroTestMemory(void *, uint64_t, uint32_t *value) {
|
bool ReadZeroTestMemory(void *, uint64_t, std::span<uint32_t> values) {
|
||||||
if (value == nullptr) {
|
std::ranges::fill(values, 0u);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*value = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12101,11 +12098,11 @@ void CheckFlattenedReadSlots(const ShaderRecompiler::IR::Program &program,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadSrtHostDword(void *, uint64_t address, uint32_t *value) {
|
bool ReadSrtHostDword(void *, uint64_t address, std::span<uint32_t> values) {
|
||||||
if (address == 0 || value == nullptr) {
|
if (address == 0 || values.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::memcpy(value, reinterpret_cast<const void *>(address), sizeof(*value));
|
std::memcpy(values.data(), reinterpret_cast<const void *>(address), values.size_bytes());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12114,18 +12111,17 @@ struct SrtHostRange {
|
||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ReadSrtHostRangeDword(void *userdata, uint64_t address, uint32_t *value) {
|
bool ReadSrtHostRangeDword(void *userdata, uint64_t address, std::span<uint32_t> values) {
|
||||||
const auto *range = static_cast<const SrtHostRange *>(userdata);
|
const auto *range = static_cast<const SrtHostRange *>(userdata);
|
||||||
if (range == nullptr || range->data == nullptr || range->count == 0 ||
|
if (range == nullptr || range->data == nullptr || range->count == 0 || values.empty()) {
|
||||||
value == nullptr) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto base = reinterpret_cast<uint64_t>(range->data);
|
const auto base = reinterpret_cast<uint64_t>(range->data);
|
||||||
const auto size = range->count * sizeof(uint32_t);
|
const auto size = range->count * sizeof(uint32_t);
|
||||||
if (address < base || address - base > size - sizeof(uint32_t)) {
|
if (address < base || values.size_bytes() > size || address - base > size - values.size_bytes()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::memcpy(value, reinterpret_cast<const void *>(address), sizeof(*value));
|
std::memcpy(values.data(), reinterpret_cast<const void *>(address), values.size_bytes());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue