mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 19:36:55 +02:00
Implement 0x12 CopyData, sampled-to-depth fix, stencil detailing
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user