Implement 0x12 CopyData, sampled-to-depth fix, stencil detailing

This commit is contained in:
nmzik
2026-07-16 19:03:31 +02:00
parent ceb7c6765e
commit 0d7c7510d7
17 changed files with 843 additions and 502 deletions
@@ -196,6 +196,7 @@ public:
template <typename T>
void WaitRegMem(uint32_t func, const T* addr, T ref, T mask, uint32_t poll, uint32_t wait_op);
void WriteData(uint32_t* dst, const uint32_t* src, uint32_t dw_num, uint32_t write_control);
void WriteReferenceClock(uint64_t dst_address, uint32_t num_bytes);
void DmaData(uint8_t engine, uint8_t dst_sel, uint8_t dst_cache_policy,
uint64_t dst_address_or_offset, uint8_t src_sel, uint8_t src_cache_policy,
uint64_t src_address_or_offset_or_immediate, uint32_t num_bytes,
@@ -2224,6 +2224,15 @@ KYTY_CP_OP_PARSER(CpOpCopyData) {
const uint32_t num_bytes = ((control >> 16u) & 0x1u) != 0 ? 8u : 4u;
const uint64_t src = buffer[1] | (static_cast<uint64_t>(buffer[2]) << 32u);
const uint64_t dst = buffer[3] | (static_cast<uint64_t>(buffer[4]) << 32u);
if (src_sel == (9u << 1u)) {
if (dst_sel != (2u << 1u) || dst == 0 || (dst & (num_bytes - 1u)) != 0) {
EXIT("unsupported reference-clock copyData, src_sel=0x%02" PRIx32
" dst_sel=0x%02" PRIx32 " dst=0x%016" PRIx64 " size=%u\n",
src_sel, dst_sel, dst, num_bytes);
}
cp->WriteReferenceClock(dst, num_bytes);
return 5;
}
const auto dma_src = CopyDataSrcToDma(src_sel);
if (dma_src == 2 && num_bytes == 8) {
EXIT("unsupported 64-bit immediate copyData\n");
+16
View File
@@ -661,6 +661,22 @@ void CommandProcessor::WriteData(uint32_t* dst, const uint32_t* src, uint32_t dw
memcpy(dst, src, static_cast<size_t>(dw_num) * 4);
}
void CommandProcessor::WriteReferenceClock(uint64_t dst_address, uint32_t num_bytes) {
Common::LockGuard lock(m_mutex);
if (dst_address == 0 || (num_bytes != sizeof(uint32_t) && num_bytes != sizeof(uint64_t)) ||
(dst_address & (num_bytes - 1u)) != 0) {
EXIT("invalid reference-clock copy, dst=0x%016" PRIx64 " size=%u\n", dst_address,
num_bytes);
}
const auto value = GraphicsRenderReadReferenceClock();
CommandProcessorGuestAccessScope guest_access(CommandProcessorGuestAccess::DirectFence,
dst_address, num_bytes);
std::memcpy(reinterpret_cast<void*>(dst_address), &value, num_bytes);
LOGF("\t copy_data reference clock: dst=0x%016" PRIx64 " value=0x%016" PRIx64
" size=%u\n",
dst_address, value, num_bytes);
}
void CommandProcessor::DmaData(uint8_t engine, uint8_t dst_sel, uint8_t dst_cache_policy,
uint64_t dst_address_or_offset, uint8_t src_sel,
uint8_t src_cache_policy,
+55 -5
View File
@@ -1919,7 +1919,32 @@ void TileConvertTiledToLinearStandard256B(void* dst, const void* src, uint32_t f
}
}
// Prospero depth-tile address table for 2D, 1xAA surfaces by element size.
// Prospero depth/stencil-tile address table for 2D, 1xAA surfaces by element size.
static constexpr uint32_t Depth64KB8XOffsetBytes(uint32_t x) {
uint32_t offset = 0;
offset ^= x & 0x0001u;
offset ^= (x << 1u) & 0x0004u;
offset ^= (x << 2u) & 0x0010u;
offset ^= (x << 3u) & 0x0040u;
offset ^= (x << 5u) & 0x0300u;
offset ^= (x << 4u) & 0x0400u;
offset ^= (x << 6u) & 0x0800u;
offset ^= (x << 7u) & 0x2000u;
offset ^= (x << 8u) & 0x8000u;
return offset;
}
static constexpr uint32_t Depth64KB8YOffsetBytes(uint32_t y) {
uint32_t offset = 0;
offset ^= (y << 1u) & 0x0002u;
offset ^= (y << 2u) & 0x0008u;
offset ^= (y << 3u) & 0x00a0u;
offset ^= (y << 5u) & 0x0f00u;
offset ^= (y << 6u) & 0x1000u;
offset ^= (y << 7u) & 0x4000u;
return offset;
}
static constexpr uint32_t Depth64KB16XOffsetBytes(uint32_t x) {
uint32_t offset = 0;
offset ^= (x << 1u) & 0x0002u;
@@ -1964,6 +1989,9 @@ static constexpr uint32_t Depth64KB32YOffsetBytes(uint32_t y) {
return offset;
}
static_assert(Depth64KB8XOffsetBytes(2) == 0x0004u);
static_assert(Depth64KB8YOffsetBytes(1) == 0x0002u);
static_assert((Depth64KB8XOffsetBytes(3) ^ Depth64KB8YOffsetBytes(5)) == 0x0027u);
static_assert(Depth64KB16XOffsetBytes(2) == 0x0008u);
static_assert(Depth64KB16YOffsetBytes(1) == 0x0004u);
static_assert((Depth64KB16XOffsetBytes(3) ^ Depth64KB16YOffsetBytes(5)) == 0x004eu);
@@ -1971,6 +1999,20 @@ static_assert(Depth64KB32XOffsetBytes(2) == 0x0010u);
static_assert(Depth64KB32YOffsetBytes(1) == 0x0008u);
static_assert((Depth64KB32XOffsetBytes(3) ^ Depth64KB32YOffsetBytes(5)) == 0x009cu);
struct Depth64KB8Tables {
std::array<uint32_t, 256> x_words {};
std::array<uint32_t, 256> y_words {};
constexpr Depth64KB8Tables() {
for (uint32_t x = 0; x < x_words.size(); x++) {
x_words[x] = Depth64KB8XOffsetBytes(x);
}
for (uint32_t y = 0; y < y_words.size(); y++) {
y_words[y] = Depth64KB8YOffsetBytes(y);
}
}
};
struct Depth64KB16Tables {
std::array<uint32_t, 256> x_words {};
std::array<uint32_t, 128> y_words {};
@@ -2089,15 +2131,19 @@ static void TileConvertDepth(void* dst, const void* src, uint32_t format, uint32
uint32_t height, uint32_t pitch, uint64_t size) {
KYTY_PROFILER_FUNCTION();
const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format);
const uint32_t block_width = bytes_per_element == 2 ? 256u : 128u;
const bool supported_bpe =
bytes_per_element == 1 || bytes_per_element == 2 || bytes_per_element == 4;
const uint32_t block_width = supported_bpe && bytes_per_element <= 2 ? 256u : 128u;
const uint32_t block_height = supported_bpe ? 65536u / (block_width * bytes_per_element) : 0;
if (dst == nullptr || src == nullptr || width == 0 || height == 0 || pitch < width ||
(bytes_per_element != 2 && bytes_per_element != 4) || pitch % block_width != 0 ||
!supported_bpe || pitch % block_width != 0 ||
size == 0 || size % 65536u != 0) {
EXIT("unsupported depth conversion, dst=%p src=%p format=%u "
"extent=%ux%u pitch=%u size=0x%016" PRIx64 "\n",
dst, src, format, width, height, pitch, size);
}
const uint64_t block_rows = (static_cast<uint64_t>(height) + 127u) / 128u;
const uint64_t block_rows =
(static_cast<uint64_t>(height) + block_height - 1u) / block_height;
const uint64_t blocks_per_row = pitch / block_width;
if (blocks_per_row > UINT64_MAX / block_rows ||
blocks_per_row * block_rows > UINT64_MAX / 65536u ||
@@ -2106,7 +2152,11 @@ static void TileConvertDepth(void* dst, const void* src, uint32_t format, uint32
"extent=%ux%u pitch=%u bpe=%u size=0x%016" PRIx64 "\n",
width, height, pitch, bytes_per_element, size);
}
if (bytes_per_element == 2) {
if (bytes_per_element == 1) {
static constexpr Depth64KB8Tables tables;
TileConvertDepthTyped<tiled_to_linear, uint8_t>(dst, src, width, height, pitch, size,
tables.x_words, tables.y_words);
} else if (bytes_per_element == 2) {
static constexpr Depth64KB16Tables tables;
TileConvertDepthTyped<tiled_to_linear, uint16_t>(dst, src, width, height, pitch, size,
tables.x_words, tables.y_words);