format source files

This commit is contained in:
nmzik
2026-07-18 08:56:38 +02:00
parent 6c1bd853ac
commit 601c82a031
53 changed files with 1622 additions and 1573 deletions
+5 -1
View File
@@ -4,13 +4,17 @@
// #error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS" // #error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else #else
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // IWYU pragma: keep
#include "common/platform/sysFileIO.h" #include "common/platform/sysFileIO.h"
#include "common/platform/sysTimer.h" #include "common/platform/sysTimer.h"
#include "common/stringUtils.h" #include "common/stringUtils.h"
#include <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
#include <windows.h> // IWYU pragma: keep
// NOLINTNEXTLINE(readability-identifier-naming) // NOLINTNEXTLINE(readability-identifier-naming)
enum sys_file_type_t { enum sys_file_type_t {
+5 -2
View File
@@ -4,12 +4,15 @@
// #error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS" // #error "KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS"
#else #else
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // IWYU pragma: keep
#include "common/assert.h" #include "common/assert.h"
#include "common/platform/sysVirtual.h" #include "common/platform/sysVirtual.h"
#include "common/virtualMemory.h" #include "common/virtualMemory.h"
#include <windows.h> // IWYU pragma: keep
// IWYU pragma: no_include <basetsd.h> // IWYU pragma: no_include <basetsd.h>
// IWYU pragma: no_include <errhandlingapi.h> // IWYU pragma: no_include <errhandlingapi.h>
// IWYU pragma: no_include <memoryapi.h> // IWYU pragma: no_include <memoryapi.h>
+8 -11
View File
@@ -28,8 +28,8 @@ constexpr FormatInfo kFormatInfo[] = {
{GpuEnumValue(BufferFormat::k16_16UInt), VK_FORMAT_R16G16_UINT, 4, 0, 4, true, true}, {GpuEnumValue(BufferFormat::k16_16UInt), VK_FORMAT_R16G16_UINT, 4, 0, 4, true, true},
{GpuEnumValue(BufferFormat::k16_16SInt), VK_FORMAT_R16G16_SINT, 4, 0, 4, false, false}, {GpuEnumValue(BufferFormat::k16_16SInt), VK_FORMAT_R16G16_SINT, 4, 0, 4, false, false},
{GpuEnumValue(BufferFormat::k16_16Float), VK_FORMAT_R16G16_SFLOAT, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k16_16Float), VK_FORMAT_R16G16_SFLOAT, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k11_11_10Float), VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 0, 4, {GpuEnumValue(BufferFormat::k11_11_10Float), VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 0, 4, true,
true, false}, false},
{GpuEnumValue(BufferFormat::k10_10_10_2UNorm), VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 0, 4, {GpuEnumValue(BufferFormat::k10_10_10_2UNorm), VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 0, 4,
true, false}, true, false},
{GpuEnumValue(BufferFormat::k8_8_8_8UNorm), VK_FORMAT_R8G8B8A8_UNORM, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k8_8_8_8UNorm), VK_FORMAT_R8G8B8A8_UNORM, 4, 0, 4, true, false},
@@ -50,28 +50,25 @@ constexpr FormatInfo kFormatInfo[] = {
{GpuEnumValue(BufferFormat::k16_16_16_16Float), VK_FORMAT_R16G16B16A16_SFLOAT, 8, 0, 8, true, {GpuEnumValue(BufferFormat::k16_16_16_16Float), VK_FORMAT_R16G16B16A16_SFLOAT, 8, 0, 8, true,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32UInt), VK_FORMAT_R32G32B32_UINT, 12, 0, 12, true, true}, {GpuEnumValue(BufferFormat::k32_32_32UInt), VK_FORMAT_R32G32B32_UINT, 12, 0, 12, true, true},
{GpuEnumValue(BufferFormat::k32_32_32SInt), VK_FORMAT_R32G32B32_SINT, 12, 0, 12, false, {GpuEnumValue(BufferFormat::k32_32_32SInt), VK_FORMAT_R32G32B32_SINT, 12, 0, 12, false, false},
false},
{GpuEnumValue(BufferFormat::k32_32_32Float), VK_FORMAT_R32G32B32_SFLOAT, 12, 0, 12, true, {GpuEnumValue(BufferFormat::k32_32_32Float), VK_FORMAT_R32G32B32_SFLOAT, 12, 0, 12, true,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32_32UInt), VK_FORMAT_R32G32B32A32_UINT, 16, 0, 16, true, {GpuEnumValue(BufferFormat::k32_32_32_32UInt), VK_FORMAT_R32G32B32A32_UINT, 16, 0, 16, true,
true}, true},
{GpuEnumValue(BufferFormat::k32_32_32_32SInt), VK_FORMAT_R32G32B32A32_SINT, 16, 0, 16, false, {GpuEnumValue(BufferFormat::k32_32_32_32SInt), VK_FORMAT_R32G32B32A32_SINT, 16, 0, 16, false,
false}, false},
{GpuEnumValue(BufferFormat::k32_32_32_32Float), VK_FORMAT_R32G32B32A32_SFLOAT, 16, 0, 16, {GpuEnumValue(BufferFormat::k32_32_32_32Float), VK_FORMAT_R32G32B32A32_SFLOAT, 16, 0, 16, true,
true, false}, false},
{GpuEnumValue(BufferFormat::k8_8_8_8Srgb), VK_FORMAT_R8G8B8A8_SRGB, 4, 0, 4, true, false}, {GpuEnumValue(BufferFormat::k8_8_8_8Srgb), VK_FORMAT_R8G8B8A8_SRGB, 4, 0, 4, true, false},
{GpuEnumValue(BufferFormat::k9_9_9_5Float), VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 4, 0, 0, true, {GpuEnumValue(BufferFormat::k9_9_9_5Float), VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 4, 0, 0, true,
false}, false},
{GpuEnumValue(BufferFormat::k5_6_5UNorm), VK_FORMAT_B5G6R5_UNORM_PACK16, 2, 0, 2, true, {GpuEnumValue(BufferFormat::k5_6_5UNorm), VK_FORMAT_B5G6R5_UNORM_PACK16, 2, 0, 2, true, false},
false},
{GpuEnumValue(BufferFormat::k5_5_5_1UNorm), VK_FORMAT_R5G5B5A1_UNORM_PACK16, 2, 0, 2, true, {GpuEnumValue(BufferFormat::k5_5_5_1UNorm), VK_FORMAT_R5G5B5A1_UNORM_PACK16, 2, 0, 2, true,
false}, false},
{GpuEnumValue(BufferFormat::k4_4_4_4UNorm), VK_FORMAT_R4G4B4A4_UNORM_PACK16, 2, 0, 2, true, {GpuEnumValue(BufferFormat::k4_4_4_4UNorm), VK_FORMAT_R4G4B4A4_UNORM_PACK16, 2, 0, 2, true,
false}, false},
{GpuEnumValue(BufferFormat::kFmask8_S4_F4), VK_FORMAT_R32_SFLOAT, 1, 0, 1, true, false}, {GpuEnumValue(BufferFormat::kFmask8_S4_F4), VK_FORMAT_R32_SFLOAT, 1, 0, 1, true, false},
{GpuEnumValue(BufferFormat::kBc1UNorm), VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 0, 8, 0, true, {GpuEnumValue(BufferFormat::kBc1UNorm), VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 0, 8, 0, true, false},
false},
{GpuEnumValue(BufferFormat::kBc1Srgb), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 0, 8, 0, true, false}, {GpuEnumValue(BufferFormat::kBc1Srgb), VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 0, 8, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2UNorm), VK_FORMAT_BC2_UNORM_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc2UNorm), VK_FORMAT_BC2_UNORM_BLOCK, 0, 16, 0, true, false},
{GpuEnumValue(BufferFormat::kBc2Srgb), VK_FORMAT_BC2_SRGB_BLOCK, 0, 16, 0, true, false}, {GpuEnumValue(BufferFormat::kBc2Srgb), VK_FORMAT_BC2_SRGB_BLOCK, 0, 16, 0, true, false},
@@ -88,7 +85,7 @@ constexpr FormatInfo kFormatInfo[] = {
}; };
constexpr auto MakeFormatInfoLookup() { constexpr auto MakeFormatInfoLookup() {
constexpr uint32_t kMaxFormat = GpuEnumValue(BufferFormat::kBc7Srgb); constexpr uint32_t kMaxFormat = GpuEnumValue(BufferFormat::kBc7Srgb);
std::array<const FormatInfo*, kMaxFormat + 1> lookup {}; std::array<const FormatInfo*, kMaxFormat + 1> lookup {};
for (const auto& info: kFormatInfo) { for (const auto& info: kFormatInfo) {
lookup[info.format] = &info; lookup[info.format] = &info;
+21 -23
View File
@@ -1526,9 +1526,7 @@ void CommandProcessor::WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_wr
switch (interrupt_selector) { switch (interrupt_selector) {
case 0x00: case 0x00:
case 0x03: with_interrupt = false; break; case 0x03: with_interrupt = false; break;
case 0x01: case 0x01: Sync::TriggerEopEventAtEndOfPipe(CurrentBuffer(), interrupt_context_id); return;
Sync::TriggerEopEventAtEndOfPipe(CurrentBuffer(), interrupt_context_id);
return;
case 0x02: with_interrupt = true; break; case 0x02: with_interrupt = true; break;
default: EXIT("unknown interrupt_selector\n"); default: EXIT("unknown interrupt_selector\n");
} }
@@ -1540,11 +1538,11 @@ void CommandProcessor::WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_wr
if (with_interrupt) { if (with_interrupt) {
if (with_writeback) { if (with_writeback) {
Sync::WriteAtEndOfPipeWithInterruptWriteBack32( Sync::WriteAtEndOfPipeWithInterruptWriteBack32(m_submit_id, CurrentBuffer(), dst,
m_submit_id, CurrentBuffer(), dst, data, interrupt_context_id); data, interrupt_context_id);
} else { } else {
Sync::WriteAtEndOfPipeWithInterrupt32(m_submit_id, CurrentBuffer(), dst, Sync::WriteAtEndOfPipeWithInterrupt32(m_submit_id, CurrentBuffer(), dst, data,
data, interrupt_context_id); interrupt_context_id);
} }
} else if (with_writeback) { } else if (with_writeback) {
Sync::WriteAtEndOfPipeWithWriteBack32(m_submit_id, CurrentBuffer(), dst, data); Sync::WriteAtEndOfPipeWithWriteBack32(m_submit_id, CurrentBuffer(), dst, data);
@@ -1560,8 +1558,8 @@ void CommandProcessor::WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_wr
auto* dst = static_cast<uint32_t*>(dst_gpu_addr); auto* dst = static_cast<uint32_t*>(dst_gpu_addr);
SynchronizeGpu(); SynchronizeGpu();
Sync::ReadGds(dst, value & 0xffffu, value >> 16u); Sync::ReadGds(dst, value & 0xffffu, value >> 16u);
Sync::WriteAtEndOfPipeGds32(m_submit_id, CurrentBuffer(), dst, Sync::WriteAtEndOfPipeGds32(m_submit_id, CurrentBuffer(), dst, value & 0xffffu,
value & 0xffffu, value >> 16u); value >> 16u);
return; return;
} }
} else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05) { } else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05) {
@@ -1588,12 +1586,12 @@ void CommandProcessor::WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_wr
Sync::WriteAtEndOfPipeWithInterruptWriteBack64( Sync::WriteAtEndOfPipeWithInterruptWriteBack64(
m_submit_id, CurrentBuffer(), dst, value, interrupt_context_id); m_submit_id, CurrentBuffer(), dst, value, interrupt_context_id);
} else { } else {
Sync::WriteAtEndOfPipeWithInterrupt64( Sync::WriteAtEndOfPipeWithInterrupt64(m_submit_id, CurrentBuffer(), dst,
m_submit_id, CurrentBuffer(), dst, value, interrupt_context_id); value, interrupt_context_id);
} }
} else if (with_writeback) { } else if (with_writeback) {
Sync::WriteAtEndOfPipeWithWriteBack64(m_submit_id, CurrentBuffer(), Sync::WriteAtEndOfPipeWithWriteBack64(m_submit_id, CurrentBuffer(), dst,
dst, value); value);
} else { } else {
Sync::WriteAtEndOfPipe64(m_submit_id, CurrentBuffer(), dst, value); Sync::WriteAtEndOfPipe64(m_submit_id, CurrentBuffer(), dst, value);
} }
@@ -1669,9 +1667,9 @@ void CommandProcessor::WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_wr
if (((eop_event_type == 0x04 && event_index == 0x05) || if (((eop_event_type == 0x04 && event_index == 0x05) ||
(eop_event_type == 0x28 && event_index == 0x00)) && (eop_event_type == 0x28 && event_index == 0x00)) &&
!with_interrupt) { !with_interrupt) {
Sync::WriteAtEndOfPipeClockCounter( Sync::WriteAtEndOfPipeClockCounter(m_submit_id, CurrentBuffer(),
m_submit_id, CurrentBuffer(), static_cast<uint64_t*>(dst_gpu_addr), static_cast<uint64_t*>(dst_gpu_addr),
clock); clock);
return; return;
} }
break; break;
@@ -1815,9 +1813,9 @@ void CommandProcessor::Flip() {
auto* command = CurrentBuffer(); auto* command = CurrentBuffer();
auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index, auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index,
m_flip.flip_mode, m_flip.flip_arg); m_flip.flip_mode, m_flip.flip_arg);
Sync::WriteAtEndOfPipeOnlyFlip(m_submit_id, command, m_flip.handle, m_flip.index, Sync::WriteAtEndOfPipeOnlyFlip(m_submit_id, command, m_flip.handle, m_flip.index,
m_flip.flip_mode, m_flip.flip_arg, request); m_flip.flip_mode, m_flip.flip_arg, request);
m_scheduler.Flush(); m_scheduler.Flush();
} }
@@ -1836,10 +1834,10 @@ void CommandProcessor::Flip(void* dst_gpu_addr, uint32_t value) {
std::memcpy(dst_gpu_addr, &value, sizeof(value)); std::memcpy(dst_gpu_addr, &value, sizeof(value));
auto* command = CurrentBuffer(); auto* command = CurrentBuffer();
auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index, auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index,
m_flip.flip_mode, m_flip.flip_arg); m_flip.flip_mode, m_flip.flip_arg);
Sync::WriteAtEndOfPipeWithFlip32( Sync::WriteAtEndOfPipeWithFlip32(m_submit_id, command, static_cast<uint32_t*>(dst_gpu_addr),
m_submit_id, command, static_cast<uint32_t*>(dst_gpu_addr), value, m_flip.handle, value, m_flip.handle, m_flip.index, m_flip.flip_mode,
m_flip.index, m_flip.flip_mode, m_flip.flip_arg, request); m_flip.flip_arg, request);
m_scheduler.Flush(); m_scheduler.Flush();
} }
@@ -1864,7 +1862,7 @@ void CommandProcessor::FlipWithInterrupt(uint32_t eop_event_type, uint32_t cache
std::memcpy(dst_gpu_addr, &value, sizeof(value)); std::memcpy(dst_gpu_addr, &value, sizeof(value));
auto* command = CurrentBuffer(); auto* command = CurrentBuffer();
auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index, auto request = Sync::PrepareDisplayBufferFlip(command, m_flip.handle, m_flip.index,
m_flip.flip_mode, m_flip.flip_arg); m_flip.flip_mode, m_flip.flip_arg);
Sync::WriteAtEndOfPipeWithInterruptWriteBackFlip32( Sync::WriteAtEndOfPipeWithInterruptWriteBackFlip32(
m_submit_id, command, static_cast<uint32_t*>(dst_gpu_addr), value, m_flip.handle, m_submit_id, command, static_cast<uint32_t*>(dst_gpu_addr), value, m_flip.handle,
m_flip.index, m_flip.flip_mode, m_flip.flip_arg, request); m_flip.index, m_flip.flip_mode, m_flip.flip_arg, request);
+41 -43
View File
@@ -299,8 +299,7 @@ static bool Gen5Standard64KBLayout(uint32_t format, uint32_t* bytes_per_element,
} }
} }
static bool Gen5Thin64KBBlockSizeFromElementBytes(uint32_t bytes_per_element, static bool Gen5Thin64KBBlockSizeFromElementBytes(uint32_t bytes_per_element, uint32_t* block_width,
uint32_t* block_width,
uint32_t* block_height) { uint32_t* block_height) {
// AGC thin 64 KiB block table, shared by depth and render-target tiles. // AGC thin 64 KiB block table, shared by depth and render-target tiles.
switch (bytes_per_element) { switch (bytes_per_element) {
@@ -1181,8 +1180,8 @@ static void ConvertRenderTargetTyped(uint32_t width, uint32_t height, uint32_t p
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes( EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes(static_cast<uint32_t>(sizeof(T)),
static_cast<uint32_t>(sizeof(T)), &block_width, &block_height)); &block_width, &block_height));
const uint64_t blocks_per_row = (static_cast<uint64_t>(pitch) + block_width - 1u) / block_width; const uint64_t blocks_per_row = (static_cast<uint64_t>(pitch) + block_width - 1u) / block_width;
const uint32_t block_columns = (width == 0 ? 0 : 1u + (width - 1u) / block_width); const uint32_t block_columns = (width == 0 ? 0 : 1u + (width - 1u) / block_width);
@@ -1487,9 +1486,9 @@ void TileConvertLinearToTiledStandard64KB32(void* dst, const void* src, uint32_t
dst, src, width, height, pitch, size); dst, src, width, height, pitch, size);
} }
auto* dst32 = static_cast<uint32_t*>(dst); auto* dst32 = static_cast<uint32_t*>(dst);
const auto* src32 = static_cast<const uint32_t*>(src); const auto* src32 = static_cast<const uint32_t*>(src);
const auto& tables = GetStandard64KB32Tables(); const auto& tables = GetStandard64KB32Tables();
const auto blocks_per_row = (static_cast<uint64_t>(pitch) + 127u) >> 7u; const auto blocks_per_row = (static_cast<uint64_t>(pitch) + 127u) >> 7u;
const auto block_rows = (static_cast<uint64_t>(height) + 127u) >> 7u; const auto block_rows = (static_cast<uint64_t>(height) + 127u) >> 7u;
if (blocks_per_row > UINT64_MAX / block_rows / 65536u || if (blocks_per_row > UINT64_MAX / block_rows / 65536u ||
@@ -1800,10 +1799,10 @@ static void TileConvertLinearToTiledStandard64KB64Elements(
"size=0x%016" PRIx64 " dst_size=0x%016" PRIx64 " dst=%u,%u\n", "size=0x%016" PRIx64 " dst_size=0x%016" PRIx64 " dst=%u,%u\n",
width_elements, height_elements, pitch_elements, size, dst_size, dst_x, dst_y); width_elements, height_elements, pitch_elements, size, dst_size, dst_x, dst_y);
} }
auto* dst64 = static_cast<uint64_t*>(dst); auto* dst64 = static_cast<uint64_t*>(dst);
const auto* src64 = static_cast<const uint64_t*>(src); const auto* src64 = static_cast<const uint64_t*>(src);
const auto& tables = GetStandard64KB64Tables(); const auto& tables = GetStandard64KB64Tables();
const auto size_words = size >> 3u; const auto size_words = size >> 3u;
const auto dst_size_words = dst_size >> 3u; const auto dst_size_words = dst_size >> 3u;
for (uint32_t y = 0; y < height_elements; y++) { for (uint32_t y = 0; y < height_elements; y++) {
const uint64_t src_row = static_cast<uint64_t>(y) * pitch_elements; const uint64_t src_row = static_cast<uint64_t>(y) * pitch_elements;
@@ -2222,14 +2221,12 @@ static void TileConvertDepth(void* dst, const void* src, uint32_t format, uint32
const uint32_t block_width = supported_bpe && bytes_per_element <= 2 ? 256u : 128u; 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; 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 || if (dst == nullptr || src == nullptr || width == 0 || height == 0 || pitch < width ||
!supported_bpe || pitch % block_width != 0 || !supported_bpe || pitch % block_width != 0 || size == 0 || size % 65536u != 0) {
size == 0 || size % 65536u != 0) {
EXIT("unsupported depth conversion, dst=%p src=%p format=%u " EXIT("unsupported depth conversion, dst=%p src=%p format=%u "
"extent=%ux%u pitch=%u size=0x%016" PRIx64 "\n", "extent=%ux%u pitch=%u size=0x%016" PRIx64 "\n",
dst, src, format, width, height, pitch, size); dst, src, format, width, height, pitch, size);
} }
const uint64_t block_rows = const uint64_t block_rows = (static_cast<uint64_t>(height) + block_height - 1u) / block_height;
(static_cast<uint64_t>(height) + block_height - 1u) / block_height;
const uint64_t blocks_per_row = pitch / block_width; const uint64_t blocks_per_row = pitch / block_width;
if (blocks_per_row > UINT64_MAX / block_rows || if (blocks_per_row > UINT64_MAX / block_rows ||
blocks_per_row * block_rows > UINT64_MAX / 65536u || blocks_per_row * block_rows > UINT64_MAX / 65536u ||
@@ -2504,13 +2501,13 @@ void TileConvertLinearToTiledRenderTarget(void* dst, const void* src, uint32_t w
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
const bool tail_block = dst_size != 0 && (dst_x != 0 || dst_y != 0 || size < dst_size); const bool tail_block = dst_size != 0 && (dst_x != 0 || dst_y != 0 || size < dst_size);
if (tail_block) { if (tail_block) {
//Not sure about this at all // Not sure about this at all
if (bytes_per_element != 8) { if (bytes_per_element != 8) {
EXIT("unsupported linear-to-tiled render-target tail element size: %u\n", EXIT("unsupported linear-to-tiled render-target tail element size: %u\n",
bytes_per_element); bytes_per_element);
} }
TileConvertLinearToTiledStandard64KB64Elements(dst, src, width, height, pitch, size, TileConvertLinearToTiledStandard64KB64Elements(dst, src, width, height, pitch, size,
dst_size, dst_x, dst_y); dst_size, dst_x, dst_y);
return; return;
} }
@@ -2596,8 +2593,8 @@ bool TileGetDepthSize(uint32_t width, uint32_t height, uint32_t pitch, uint32_t
uint32_t TileGetRenderTargetPitch(uint32_t width, uint32_t bytes_per_element) { uint32_t TileGetRenderTargetPitch(uint32_t width, uint32_t bytes_per_element) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
if (width == 0 || !Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, if (width == 0 ||
&block_height)) { !Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, &block_height)) {
return 0; return 0;
} }
const uint64_t pitch = (static_cast<uint64_t>(width) + block_width - 1u) & const uint64_t pitch = (static_cast<uint64_t>(width) + block_width - 1u) &
@@ -2611,8 +2608,7 @@ bool TileGetRenderTargetSize(uint32_t width, uint32_t height, uint32_t pitch,
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
if (height == 0 || pitch == 0 || if (height == 0 || pitch == 0 ||
!Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, !Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, &block_height) ||
&block_height) ||
pitch != TileGetRenderTargetPitch(width, bytes_per_element)) { pitch != TileGetRenderTargetPitch(width, bytes_per_element)) {
return false; return false;
} }
@@ -2655,8 +2651,8 @@ bool TileGetRenderTargetMipLayout(uint32_t width, uint32_t height, uint32_t pitc
default: return false; default: return false;
} }
TileGetTextureSize(format, width, height, pitch, levels, TileGetTextureSize(format, width, height, pitch, levels,
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget), total_size, level_sizes, Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget), total_size,
padded_size); level_sizes, padded_size);
return total_size->size != 0 && total_size->align == 65536; return total_size->size != 0 && total_size->align == 65536;
} }
@@ -2738,8 +2734,8 @@ void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32
bytes_per_element != 0 && tile == 27 && levels == 1) { bytes_per_element != 0 && tile == 27 && levels == 1) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes( EXIT_NOT_IMPLEMENTED(
bytes_per_element, &block_width, &block_height)); !Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, &block_height));
const uint32_t padded_width = AlignUp(pitch, block_width); const uint32_t padded_width = AlignUp(pitch, block_width);
const uint32_t padded_height = AlignUp(height, block_height); const uint32_t padded_height = AlignUp(height, block_height);
@@ -2767,8 +2763,8 @@ void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32
bytes_per_element != 0 && tile == 27 && levels > 1) { bytes_per_element != 0 && tile == 27 && levels > 1) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes( EXIT_NOT_IMPLEMENTED(
bytes_per_element, &block_width, &block_height)); !Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, &block_height));
const uint32_t bytes_log2 = IntLog2(bytes_per_element); const uint32_t bytes_log2 = IntLog2(bytes_per_element);
const uint32_t tail_width_limit = block_width >> 1u; const uint32_t tail_width_limit = block_width >> 1u;
@@ -2990,11 +2986,11 @@ void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32
if (tile == 24 && levels == 1) { if (tile == 24 && levels == 1) {
const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format); const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format);
if (bytes_per_element != 0) { if (bytes_per_element != 0) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
const bool supported = bytes_per_element <= 4 && const bool supported =
Gen5Thin64KBBlockSizeFromElementBytes( bytes_per_element <= 4 && Gen5Thin64KBBlockSizeFromElementBytes(
bytes_per_element, &block_width, &block_height); bytes_per_element, &block_width, &block_height);
if (supported) { if (supported) {
const uint32_t padded_width = (pitch + block_width - 1u) & ~(block_width - 1u); const uint32_t padded_width = (pitch + block_width - 1u) & ~(block_width - 1u);
@@ -3024,11 +3020,11 @@ void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32
if (tile == 24 && levels > 1) { if (tile == 24 && levels > 1) {
const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format); const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format);
if (bytes_per_element != 0) { if (bytes_per_element != 0) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
const bool supported = bytes_per_element <= 4 && const bool supported =
Gen5Thin64KBBlockSizeFromElementBytes( bytes_per_element <= 4 && Gen5Thin64KBBlockSizeFromElementBytes(
bytes_per_element, &block_width, &block_height); bytes_per_element, &block_width, &block_height);
if (supported) { if (supported) {
static bool logged = false; static bool logged = false;
@@ -3271,7 +3267,8 @@ uint32_t TileGetTexturePitch(uint32_t format, uint32_t width, uint32_t levels, u
uint32_t pitch = width; uint32_t pitch = width;
if (tile == 27) { if (tile == 27) {
if (const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format); bytes_per_element != 0) { if (const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format);
bytes_per_element != 0) {
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes( EXIT_NOT_IMPLEMENTED(!Gen5Thin64KBBlockSizeFromElementBytes(
@@ -3281,7 +3278,8 @@ uint32_t TileGetTexturePitch(uint32_t format, uint32_t width, uint32_t levels, u
} }
if (tile == 0) { if (tile == 0) {
if (const auto bytes_per_element = Prospero::NumBytesPerElement(format); bytes_per_element != 0) { if (const auto bytes_per_element = Prospero::NumBytesPerElement(format);
bytes_per_element != 0) {
pitch = AlignUp(pitch * bytes_per_element, 256u) / bytes_per_element; pitch = AlignUp(pitch * bytes_per_element, 256u) / bytes_per_element;
} }
} }
@@ -3297,10 +3295,10 @@ uint32_t TileGetTexturePitch(uint32_t format, uint32_t width, uint32_t levels, u
} }
if (tile == 24) { if (tile == 24) {
const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format); const uint32_t bytes_per_element = Prospero::NumBytesPerElement(format);
uint32_t block_width = 0; uint32_t block_width = 0;
uint32_t block_height = 0; uint32_t block_height = 0;
if (bytes_per_element <= 4 && Gen5Thin64KBBlockSizeFromElementBytes( if (bytes_per_element <= 4 &&
bytes_per_element, &block_width, &block_height)) { Gen5Thin64KBBlockSizeFromElementBytes(bytes_per_element, &block_width, &block_height)) {
pitch = AlignUp(pitch, block_width); pitch = AlignUp(pitch, block_width);
} }
} }
+10 -10
View File
@@ -19,16 +19,16 @@ class CommandBuffer;
struct VulkanSwapchain { struct VulkanSwapchain {
~VulkanSwapchain(); ~VulkanSwapchain();
VkSwapchainKHR swapchain = nullptr; VkSwapchainKHR swapchain = nullptr;
VkFormat swapchain_format = VK_FORMAT_UNDEFINED; VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
VkExtent2D swapchain_extent = {}; VkExtent2D swapchain_extent = {};
std::unique_ptr<VkImage[]> swapchain_images; std::unique_ptr<VkImage[]> swapchain_images;
std::unique_ptr<VkImageView[]> swapchain_image_views; std::unique_ptr<VkImageView[]> swapchain_image_views;
uint32_t swapchain_images_count = 0; uint32_t swapchain_images_count = 0;
std::unique_ptr<VkSemaphore[]> image_acquired_semaphores; std::unique_ptr<VkSemaphore[]> image_acquired_semaphores;
std::unique_ptr<VkSemaphore[]> render_complete_semaphores; std::unique_ptr<VkSemaphore[]> render_complete_semaphores;
uint32_t current_index = 0; uint32_t current_index = 0;
uint32_t present_frame = 0; uint32_t present_frame = 0;
}; };
struct VulkanCommandPool { struct VulkanCommandPool {
+8 -8
View File
@@ -37,9 +37,9 @@ thread_local bool g_in_fault_resolution = false;
std::fputs(reason != nullptr ? reason : "invalid page state", stderr); std::fputs(reason != nullptr ? reason : "invalid page state", stderr);
std::fputc('\n', stderr); std::fputc('\n', stderr);
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
void* frames[16] {}; void* frames[16] {};
const auto frame_count = CaptureStackBackTrace(0, static_cast<DWORD>(std::size(frames)), frames, const auto frame_count =
nullptr); CaptureStackBackTrace(0, static_cast<DWORD>(std::size(frames)), frames, nullptr);
const auto image_base = reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr)); const auto image_base = reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr));
for (uint16_t i = 0; i < frame_count; i++) { for (uint16_t i = 0; i < frame_count; i++) {
const auto address = reinterpret_cast<uintptr_t>(frames[i]); const auto address = reinterpret_cast<uintptr_t>(frames[i]);
@@ -572,17 +572,17 @@ bool PageManager::HandleFault(PageFaultAccess access, uint64_t fault_vaddr) noex
if (access != PageFaultAccess::Read && access != PageFaultAccess::Write) { if (access != PageFaultAccess::Read && access != PageFaultAccess::Write) {
return false; return false;
} }
bool& pending = (access == PageFaultAccess::Read ? page.late_read_pending bool& pending = (access == PageFaultAccess::Read ? page.late_read_pending
: page.late_write_pending); : page.late_write_pending);
const bool allowed = Impl::AllowsAccess(fault_vaddr, access); const bool allowed = Impl::AllowsAccess(fault_vaddr, access);
pending = false; pending = false;
if (waited && !allowed) { if (waited && !allowed) {
FailFast("page remained inaccessible after waiting for its resolver"); FailFast("page remained inaccessible after waiting for its resolver");
} }
// More than one CPU can fault before a protection transition becomes visible. The first // More than one CPU can fault before a protection transition becomes visible. The first
// delayed fault consumes the hint bit; later faults must also resume once the mapped page // delayed fault consumes the hint bit; later faults must also resume once the mapped
// already permits the requested access. A genuinely read-only/no-access page still falls // page already permits the requested access. A genuinely read-only/no-access page still
// through to the guest exception path. // falls through to the guest exception path.
return allowed; return allowed;
} }
if ((access != PageFaultAccess::Read && access != PageFaultAccess::Write) || if ((access != PageFaultAccess::Read && access != PageFaultAccess::Write) ||
@@ -683,8 +683,8 @@ std::pair<VulkanBuffer*, uint64_t> BufferCache::ObtainBuffer(CommandBuffer* com
// host page protection is irrelevant. // host page protection is irrelevant.
if (is_read && !is_written && size <= CACHING_PAGE_SIZE && if (is_read && !is_written && size <= CACHING_PAGE_SIZE &&
!m_memory_tracker.IsRegionGpuModified(vaddr, size) && !m_memory_tracker.IsRegionGpuModified(vaddr, size) &&
m_memory_tracker.IsRegionCpuModified(vaddr, size) && m_memory_tracker.IsRegionCpuModified(vaddr, size) && !texture_region.gpu_image_bytes &&
!texture_region.gpu_image_bytes && !texture_region.gpu_metadata_bytes) { !texture_region.gpu_metadata_bytes) {
std::array<uint8_t, CACHING_PAGE_SIZE> guest_data; std::array<uint8_t, CACHING_PAGE_SIZE> guest_data;
if (Libs::LibKernel::Memory::TryReadBacking(vaddr, guest_data.data(), size)) { if (Libs::LibKernel::Memory::TryReadBacking(vaddr, guest_data.data(), size)) {
VulkanBuffer* stream_buffer = nullptr; VulkanBuffer* stream_buffer = nullptr;
@@ -1143,10 +1143,10 @@ void BufferCache::CopyBuffer(CommandBuffer* command, GraphicContext* ctx, uint64
bool dst_image_transition = false; bool dst_image_transition = false;
{ {
std::lock_guard transaction(m_resource_mutex); std::lock_guard transaction(m_resource_mutex);
const auto src_region = m_texture_cache->QueryRegion(src_vaddr, size); const auto src_region = m_texture_cache->QueryRegion(src_vaddr, size);
const auto dst_region = m_texture_cache->QueryRegion(dst_vaddr, size); const auto dst_region = m_texture_cache->QueryRegion(dst_vaddr, size);
const bool src_image_gpu = src_region.gpu_image_bytes; const bool src_image_gpu = src_region.gpu_image_bytes;
const bool src_meta = src_region.metadata_bytes; const bool src_meta = src_region.metadata_bytes;
if (src_region.non_sampled_pages) { if (src_region.non_sampled_pages) {
EXIT("BufferCache: GPU copy aliases target pages, src=0x%016" PRIx64 EXIT("BufferCache: GPU copy aliases target pages, src=0x%016" PRIx64
" dst=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", " dst=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
@@ -1174,7 +1174,7 @@ void BufferCache::CopyBuffer(CommandBuffer* command, GraphicContext* ctx, uint64
" dst=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", " dst=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
src_vaddr, dst_vaddr, size); src_vaddr, dst_vaddr, size);
} }
dst_image_transition = m_texture_cache->InvalidateMemoryFromGPU(dst_vaddr, size); dst_image_transition = m_texture_cache->InvalidateMemoryFromGPU(dst_vaddr, size);
const auto transitioned_dst = m_texture_cache->QueryRegion(dst_vaddr, size); const auto transitioned_dst = m_texture_cache->QueryRegion(dst_vaddr, size);
// A clean target destination is handled above like a protected host write. Target // A clean target destination is handled above like a protected host write. Target
// aliases that require an actual GPU buffer copy remain unsupported. // aliases that require an actual GPU buffer copy remain unsupported.
@@ -11,8 +11,8 @@
#include "graphics/guest_gpu/tile.h" #include "graphics/guest_gpu/tile.h"
#include "graphics/host_gpu/graphicContext.h" #include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/objects/textureCommon.h" #include "graphics/host_gpu/objects/textureCommon.h"
#include "graphics/host_gpu/renderer/descriptorCache.h"
#include "graphics/host_gpu/renderer/debug.h" #include "graphics/host_gpu/renderer/debug.h"
#include "graphics/host_gpu/renderer/descriptorCache.h"
#include "graphics/host_gpu/renderer/framebufferCache.h" #include "graphics/host_gpu/renderer/framebufferCache.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
@@ -374,11 +374,11 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
r->color_clear_enable = false; r->color_clear_enable = false;
r->color_clear_value = {}; r->color_clear_value = {};
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t pitch = 0; uint32_t pitch = 0;
uint64_t size = 0; uint64_t size = 0;
bool tile = false; bool tile = false;
const bool standard64 = const bool standard64 =
rt.attrib3.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB); rt.attrib3.tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB);
@@ -402,9 +402,8 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
} }
if (standard64 && if (standard64 &&
(rt.attrib3.dimension != 1 || rt.attrib3.depth != 0 || levels != 1 || (rt.attrib3.dimension != 1 || rt.attrib3.depth != 0 || levels != 1 ||
rt.view.current_mip_level != 0 || rt.view.current_mip_level != 0 || view.base_layer != 0 || view.image_layers != 1 ||
view.base_layer != 0 || view.image_layers != 1 || rt.attrib.num_samples != 0 || rt.attrib.num_samples != 0 || rt.attrib.num_fragments != 0 || bytes_per_element != 4 ||
rt.attrib.num_fragments != 0 || bytes_per_element != 4 ||
rt.pitch.pitch_div8_minus1 != 0 || (rt.base.addr & 0xffffu) != 0 || rt.pitch.pitch_div8_minus1 != 0 || (rt.base.addr & 0xffffu) != 0 ||
rt.info.fmask_compression_enable || rt.info.fmask_data_compression_disable || rt.info.fmask_compression_enable || rt.info.fmask_data_compression_disable ||
rt.info.fmask_one_frag_mode || rt.info.cmask_fast_clear_enable || rt.info.fmask_one_frag_mode || rt.info.cmask_fast_clear_enable ||
@@ -415,9 +414,8 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
" dimension=%u depth=%u levels=%u layer=%u/%u samples=%u fragments=%u bpe=%u" " dimension=%u depth=%u levels=%u layer=%u/%u samples=%u fragments=%u bpe=%u"
" cmask=0x%016" PRIx64 " fmask=0x%016" PRIx64 " dcc=0x%016" PRIx64 "\n", " cmask=0x%016" PRIx64 " fmask=0x%016" PRIx64 " dcc=0x%016" PRIx64 "\n",
rt.base.addr, rt.attrib3.dimension, rt.attrib3.depth, levels, view.base_layer, rt.base.addr, rt.attrib3.dimension, rt.attrib3.depth, levels, view.base_layer,
view.image_layers, view.image_layers, rt.attrib.num_samples, rt.attrib.num_fragments, bytes_per_element,
rt.attrib.num_samples, rt.attrib.num_fragments, bytes_per_element, rt.cmask.addr, rt.cmask.addr, rt.fmask.addr, rt.dcc_addr.addr);
rt.fmask.addr, rt.dcc_addr.addr);
} }
if (rt.pitch.pitch_div8_minus1 != 0) { if (rt.pitch.pitch_div8_minus1 != 0) {
pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u; pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u;
@@ -438,7 +436,8 @@ void ResolveRenderColorTarget(uint64_t submit_id, CommandBuffer* buffer, const H
bool valid_layout = false; bool valid_layout = false;
if (standard64) { if (standard64) {
TileGetTextureSize(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), width, TileGetTextureSize(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), width,
height, pitch, levels, rt.attrib3.tile_mode, &layout, nullptr, nullptr); height, pitch, levels, rt.attrib3.tile_mode, &layout, nullptr,
nullptr);
valid_layout = layout.size != 0 && layout.align == 65536; valid_layout = layout.size != 0 && layout.align == 65536;
} else { } else {
valid_layout = valid_layout =
+1 -1
View File
@@ -5,8 +5,8 @@
#include "common/emulatorConfig.h" #include "common/emulatorConfig.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/stringUtils.h" #include "common/stringUtils.h"
#include "graphics/guest_gpu/hardwareContext.h"
#include "graphics/guest_gpu/gpu_defs.h" #include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/hardwareContext.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include <atomic> #include <atomic>
@@ -129,10 +129,9 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
// DB_DEPTH_SIZE_XY is independent state and may remain programmed after the attachment // DB_DEPTH_SIZE_XY is independent state and may remain programmed after the attachment
// formats and addresses are unbound. A zero encoding is the valid 1x1 value, so its // formats and addresses are unbound. A zero encoding is the valid 1x1 value, so its
// presence alone must not manufacture a depth attachment. // presence alone must not manufacture a depth attachment.
!z.z_info.tile_surface_enable && !z.width_height_valid && !z.z_info.tile_surface_enable && !z.width_height_valid && !z.pitch_height_valid &&
!z.pitch_height_valid && z.size.x_max == 0 && z.size.y_max == 0 && z.size.x_max == 0 && z.size.y_max == 0 && z.pitch_div8_minus1 == 0 &&
z.pitch_div8_minus1 == 0 && z.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 && z.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 && z.width == 0 && z.height == 0;
z.width == 0 && z.height == 0;
if (attachment_unbound) { if (attachment_unbound) {
static std::atomic_bool logged = false; static std::atomic_bool logged = false;
if (!logged.exchange(true, std::memory_order_relaxed)) { if (!logged.exchange(true, std::memory_order_relaxed)) {
+62 -62
View File
@@ -148,61 +148,61 @@ NativeSamplerDescriptor(const ShaderRecompiler::IR::DescriptorValue& descriptor)
} }
static BufferView NativeStorageBuffer(uint64_t submit_id, CommandBuffer* command_buffer, static BufferView NativeStorageBuffer(uint64_t submit_id, CommandBuffer* command_buffer,
const ShaderBufferResource& descriptor, const ShaderBufferResource& descriptor,
const ShaderRecompiler::IR::BufferResource& resource) { const ShaderRecompiler::IR::BufferResource& resource) {
BufferView result; BufferView result;
//Regression // Regression
// Bind a null buffer when these four dwords are // Bind a null buffer when these four dwords are
// the tracked prefix of an active image sharp. Image validity is encoded by dword 3 bit 31. // the tracked prefix of an active image sharp. Image validity is encoded by dword 3 bit 31.
/*if (resource.image_alias != ShaderRecompiler::IR::BufferResource::NoImageAlias && /*if (resource.image_alias != ShaderRecompiler::IR::BufferResource::NoImageAlias &&
(descriptor.Type() & 2u) != 0) { (descriptor.Type() & 2u) != 0) {
BindNullStorageBuffer(command_buffer, &result); BindNullStorageBuffer(command_buffer, &result);
return result; return result;
} }
// Buffer TYPE is zero. A nonzero value means a buffer instruction received the first four // Buffer TYPE is zero. A nonzero value means a buffer instruction received the first four
// dwords of an image sharp without a tracked image alias; support the known write-only path. // dwords of an image sharp without a tracked image alias; support the known write-only path.
if (descriptor.Type() != 0) { if (descriptor.Type() != 0) {
ShaderTextureResource texture {}; ShaderTextureResource texture {};
std::copy_n(descriptor.fields, 4, texture.fields); std::copy_n(descriptor.fields, 4, texture.fields);
const auto width = static_cast<uint32_t>(texture.Width5()) + 1u; const auto width = static_cast<uint32_t>(texture.Width5()) + 1u;
const auto height = static_cast<uint32_t>(texture.Height5()) + 1u; const auto height = static_cast<uint32_t>(texture.Height5()) + 1u;
const auto format = texture.Format(); const auto format = texture.Format();
const auto tile = texture.TileMode(); const auto tile = texture.TileMode();
const auto type = texture.Type(); const auto type = texture.Type();
const auto address = texture.Base40(); const auto address = texture.Base40();
const auto pitch = TileGetTexturePitch(format, width, 1, tile); const auto pitch = TileGetTexturePitch(format, width, 1, tile);
TileSizeAlign footprint {}; TileSizeAlign footprint {};
TileGetTextureTotalSize(format, width, height, 1, pitch, 1, tile, false, &footprint); TileGetTextureTotalSize(format, width, height, 1, pitch, 1, tile, false, &footprint);
const bool supported = const bool supported =
resource.formatted && resource.written && !resource.read && !resource.atomic && resource.formatted && resource.written && !resource.read && !resource.atomic &&
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UInt) && format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UInt) &&
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) && tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) &&
texture.DstSelXYZW() == DstSel(4, 5, 6, 7) && address != 0 && footprint.size != 0 && texture.DstSelXYZW() == DstSel(4, 5, 6, 7) && address != 0 && footprint.size != 0 &&
footprint.align == 65536; footprint.align == 65536;
if (!supported) { if (!supported) {
EXIT("unsupported texture descriptor used as storage buffer: type=%u format=%u" EXIT("unsupported texture descriptor used as storage buffer: type=%u format=%u"
" tile=%u swizzle=0x%03x extent=%ux%u read=%d written=%d formatted=%d atomic=%d\n", " tile=%u swizzle=0x%03x extent=%ux%u read=%d written=%d formatted=%d atomic=%d\n",
type, format, tile, texture.DstSelXYZW(), width, height, resource.read, type, format, tile, texture.DstSelXYZW(), width, height, resource.read,
resource.written, resource.formatted, resource.atomic); resource.written, resource.formatted, resource.atomic);
} }
auto* ctx = g_render_ctx->GetGraphicCtx(); auto* ctx = g_render_ctx->GetGraphicCtx();
g_render_ctx->GetBufferCache()->ValidateGpuAccess(address, footprint.size, false, true); g_render_ctx->GetBufferCache()->ValidateGpuAccess(address, footprint.size, false, true);
auto binding = g_render_ctx->GetBufferCache()->ObtainBuffer( auto binding = g_render_ctx->GetBufferCache()->ObtainBuffer(
command_buffer, ctx, address, footprint.size, true, false, true); command_buffer, ctx, address, footprint.size, true, false, true);
const auto alignment = ctx->StorageMinAlignment(); const auto alignment = ctx->StorageMinAlignment();
if (alignment == 0 || binding.second % alignment != 0 || if (alignment == 0 || binding.second % alignment != 0 ||
footprint.size > ctx->GetPhysicalDeviceProperties().limits.maxStorageBufferRange) { footprint.size > ctx->GetPhysicalDeviceProperties().limits.maxStorageBufferRange) {
EXIT("texture-backed storage buffer binding is unsupported: addr=0x%016" PRIx64 EXIT("texture-backed storage buffer binding is unsupported: addr=0x%016" PRIx64
" size=0x%016" PRIx64 " offset=0x%016" PRIx64 " alignment=0x%016" PRIx64 "\n", " size=0x%016" PRIx64 " offset=0x%016" PRIx64 " alignment=0x%016" PRIx64 "\n",
address, footprint.size, static_cast<uint64_t>(binding.second), address, footprint.size, static_cast<uint64_t>(binding.second),
static_cast<uint64_t>(alignment)); static_cast<uint64_t>(alignment));
} }
result.buffer = binding.first; result.buffer = binding.first;
result.offset = binding.second; result.offset = binding.second;
result.range = footprint.size; result.range = footprint.size;
return result; return result;
}*/ }*/
const auto address = descriptor.Base48(); const auto address = descriptor.Base48();
const auto stride = descriptor.Stride(); const auto stride = descriptor.Stride();
@@ -299,9 +299,9 @@ static bool IsSupportedSampledColorResource(const ShaderRecompiler::IR::ImageRes
!resource.written && !resource.atomic && !resource.depth_compare; !resource.written && !resource.atomic && !resource.depth_compare;
} }
TargetTextureViewInfo TargetTextureViewInfo ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource,
ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource, Prospero::ImageType type, uint32_t base_layer,
Prospero::ImageType type, uint32_t base_layer, uint32_t image_layers) { uint32_t image_layers) {
switch (type) { switch (type) {
case Prospero::ImageType::kColor2D: case Prospero::ImageType::kColor2D:
return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && return resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D &&
@@ -338,16 +338,15 @@ bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor,
const auto height = static_cast<uint32_t>(descriptor.Height5()) + 1u; const auto height = static_cast<uint32_t>(descriptor.Height5()) + 1u;
const auto pitch = TileGetTexturePitch(descriptor.Format(), width, 1, descriptor.TileMode()); const auto pitch = TileGetTexturePitch(descriptor.Format(), width, 1, descriptor.TileMode());
const auto type = static_cast<Prospero::ImageType>(descriptor.Type()); const auto type = static_cast<Prospero::ImageType>(descriptor.Type());
const bool supported_type = type == Prospero::ImageType::kColor2D || const bool supported_type =
type == Prospero::ImageType::kColor2DArray; type == Prospero::ImageType::kColor2D || type == Prospero::ImageType::kColor2DArray;
return image.type == VulkanImageType::DepthStencil && image.layers == 1 && return image.type == VulkanImageType::DepthStencil && image.layers == 1 &&
width == image.extent.width && height == image.extent.height && width == image.extent.width && height == image.extent.height &&
descriptor.Depth() == 0 && descriptor.BaseLevel() == 0 && descriptor.LastLevel() == 0 && descriptor.Depth() == 0 && descriptor.BaseLevel() == 0 && descriptor.LastLevel() == 0 &&
descriptor.MaxMip() == 0 && descriptor.MinLod() == 0 && descriptor.BaseArray5() == 0 && descriptor.MaxMip() == 0 && descriptor.MinLod() == 0 && descriptor.BaseArray5() == 0 &&
descriptor.TileMode() == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && descriptor.TileMode() == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) &&
supported_type && supported_type && descriptor.BCSwizzle() == 0 && !descriptor.MsaaDepth() &&
descriptor.BCSwizzle() == 0 && !descriptor.MsaaDepth() && pitch >= width && pitch >= width && pitch == image.guest_pitch;
pitch == image.guest_pitch;
} }
static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descriptor) { static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descriptor) {
@@ -355,13 +354,13 @@ static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descrip
constexpr uint32_t field2_reserved_mask = 0xf0003000u; constexpr uint32_t field2_reserved_mask = 0xf0003000u;
constexpr uint32_t field3_common = 0x01800000u; constexpr uint32_t field3_common = 0x01800000u;
constexpr uint32_t field5_expected = 0x00700000u; constexpr uint32_t field5_expected = 0x00700000u;
const uint32_t field3_expected = const uint32_t field3_expected =
(descriptor.Type() << 28u) | field3_common | descriptor.DstSelXYZW(); (descriptor.Type() << 28u) | field3_common | descriptor.DstSelXYZW();
return (descriptor.fields[1] & field1_reserved_mask) == 0 && return (descriptor.fields[1] & field1_reserved_mask) == 0 &&
(descriptor.fields[2] & field2_reserved_mask) == 0 && (descriptor.fields[2] & field2_reserved_mask) == 0 &&
descriptor.fields[3] == field3_expected && descriptor.fields[3] == field3_expected && descriptor.fields[4] == 0 &&
descriptor.fields[4] == 0 && descriptor.fields[5] == field5_expected && descriptor.fields[5] == field5_expected && descriptor.fields[6] == 0 &&
descriptor.fields[6] == 0 && descriptor.fields[7] == 0; descriptor.fields[7] == 0;
} }
static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource, static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource,
@@ -567,8 +566,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
descriptor.MsaaDepth(); descriptor.MsaaDepth();
if (image == nullptr) { if (image == nullptr) {
if (check_depth) { if (check_depth) {
image = g_render_ctx->GetTextureCache()->FindDepthTargetByRange( image = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(command_buffer, address,
command_buffer, address, size.size, true); size.size, true);
} else { } else {
image = g_render_ctx->GetTextureCache()->FindRenderTargetByRange(command_buffer, image = g_render_ctx->GetTextureCache()->FindRenderTargetByRange(command_buffer,
address, size.size); address, size.size);
@@ -594,7 +593,8 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer,
resource, type, descriptor.BaseArray5(), image->layers); resource, type, descriptor.BaseArray5(), image->layers);
ValidateDepthTargetBinding(resource, descriptor, image, view_format, size.size); ValidateDepthTargetBinding(resource, descriptor, image, view_format, size.size);
if (depth_view.type == VK_IMAGE_VIEW_TYPE_MAX_ENUM) { if (depth_view.type == VK_IMAGE_VIEW_TYPE_MAX_ENUM) {
EXIT("unsupported sampled depth target view: dimension=%u descriptor_type=%u " EXIT("unsupported sampled depth target view: dimension=%u "
"descriptor_type=%u "
"base_array=%u image_layers=%u\n", "base_array=%u image_layers=%u\n",
static_cast<uint32_t>(resource.dimension), descriptor.Type(), static_cast<uint32_t>(resource.dimension), descriptor.Type(),
descriptor.BaseArray5(), image->layers); descriptor.BaseArray5(), image->layers);
+1 -2
View File
@@ -19,8 +19,7 @@ struct TargetTextureViewInfo {
[[nodiscard]] TargetTextureViewInfo [[nodiscard]] TargetTextureViewInfo
ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource, ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource,
Prospero::ImageType type, uint32_t base_layer, Prospero::ImageType type, uint32_t base_layer, uint32_t image_layers);
uint32_t image_layers);
[[nodiscard]] bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, [[nodiscard]] bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor,
const VulkanImage& image); const VulkanImage& image);
@@ -34,7 +34,7 @@ DummyTextureCache::~DummyTextureCache() {
} }
VulkanImage* DummyTextureCache::Get(GraphicContext* ctx, Usage usage, bool uint_format, VulkanImage* DummyTextureCache::Get(GraphicContext* ctx, Usage usage, bool uint_format,
bool image_3d) { bool image_3d) {
Common::LockGuard lock(m_mutex); Common::LockGuard lock(m_mutex);
if (ctx == nullptr) { if (ctx == nullptr) {
EXIT("TextureCache: dummy texture requires a graphics context\n"); EXIT("TextureCache: dummy texture requires a graphics context\n");
@@ -12,7 +12,7 @@ namespace Libs::Graphics {
class DummyTextureCache final { class DummyTextureCache final {
public: public:
enum class Usage: uint8_t { Sampled, Storage }; enum class Usage : uint8_t { Sampled, Storage };
DummyTextureCache() = default; DummyTextureCache() = default;
~DummyTextureCache(); ~DummyTextureCache();
+22 -23
View File
@@ -40,10 +40,9 @@ TextureImageCreateParams MakeImageParams(const ImageInfo& info, bool storage) {
params.image_layout = TextureUploadDestination::MipLevels; params.image_layout = TextureUploadDestination::MipLevels;
params.allow_cube_view = !storage; params.allow_cube_view = !storage;
params.compatible_format_views = params.compatible_format_views =
storage && storage && (IsRgba8SrgbViewFormat(TextureGetFormat(info.format, params.format_usage)) ||
(IsRgba8SrgbViewFormat(TextureGetFormat(info.format, params.format_usage)) || info.format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
info.format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) || info.format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float));
info.format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float));
params.owner = storage ? "StorageTextureCache" : "TextureCache"; params.owner = storage ? "StorageTextureCache" : "TextureCache";
return params; return params;
} }
@@ -60,7 +59,8 @@ bool RenderTargetSupportsStorage(GraphicContext* ctx, VkFormat format, VkImageCr
VkImageCreateFlags RenderTargetCreateFlags(VkFormat format) { VkImageCreateFlags RenderTargetCreateFlags(VkFormat format) {
const bool compatible_format_view = const bool compatible_format_view =
IsRgba8SrgbViewFormat(format) || BgraToRgbaSampledViewFormat(format) != VK_FORMAT_UNDEFINED || IsRgba8SrgbViewFormat(format) ||
BgraToRgbaSampledViewFormat(format) != VK_FORMAT_UNDEFINED ||
format == VK_FORMAT_R8G8B8A8_UINT || format == VK_FORMAT_R16G16B16A16_SFLOAT || format == VK_FORMAT_R8G8B8A8_UINT || format == VK_FORMAT_R16G16B16A16_SFLOAT ||
format == VK_FORMAT_R16G16B16A16_UINT; format == VK_FORMAT_R16G16B16A16_UINT;
return compatible_format_view return compatible_format_view
@@ -69,7 +69,7 @@ VkImageCreateFlags RenderTargetCreateFlags(VkFormat format) {
} }
VkImageUsageFlags RenderTargetUsage(GraphicContext* ctx, VkFormat format, VkImageUsageFlags RenderTargetUsage(GraphicContext* ctx, VkFormat format,
VkImageCreateFlags flags) { VkImageCreateFlags flags) {
auto usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) | auto usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) |
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) | static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) |
@@ -107,8 +107,7 @@ static constexpr uint32_t DummyTextureSwizzle() {
} }
TextureImageCreateParams MakeDummyTextureParams(bool uint_format, bool image_3d, TextureImageCreateParams MakeDummyTextureParams(bool uint_format, bool image_3d,
TextureFormatUsage usage, TextureFormatUsage usage, const char* owner) {
const char* owner) {
TextureImageCreateParams params {}; TextureImageCreateParams params {};
params.fmt = static_cast<uint32_t>( params.fmt = static_cast<uint32_t>(
Prospero::GpuEnumValue(uint_format ? Prospero::BufferFormat::k8_8_8_8UInt Prospero::GpuEnumValue(uint_format ? Prospero::BufferFormat::k8_8_8_8UInt
@@ -140,7 +139,7 @@ uint32_t RenderTargetTransferFormat(uint32_t bytes_per_element) {
} }
GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage, GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage,
VulkanMemory* memory, VkComponentMapping* components) { VulkanMemory* memory, VkComponentMapping* components) {
if (components == nullptr) { if (components == nullptr) {
EXIT("TextureCache: invalid texture component output\n"); EXIT("TextureCache: invalid texture component output\n");
} }
@@ -151,7 +150,7 @@ GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info,
} }
void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info, void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
bool storage, VkComponentMapping components) { bool storage, VkComponentMapping components) {
if (storage) { if (storage) {
TextureCreateImageViews(ctx, image, components, info.type, 0, 0, 1, info.depth, false, TextureCreateImageViews(ctx, image, components, info.type, 0, 0, 1, info.depth, false,
TextureFormatUsage::Sampled | TextureFormatUsage::Storage); TextureFormatUsage::Sampled | TextureFormatUsage::Storage);
@@ -162,8 +161,8 @@ void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const
} }
void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* image, void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* image,
const RenderTargetInfo& info, uint32_t base_layer, const RenderTargetInfo& info, uint32_t base_layer,
uint32_t layer_count, bool refresh) { uint32_t layer_count, bool refresh) {
if (info.layers == 0 || info.size % info.layers != 0 || layer_count == 0 || if (info.layers == 0 || info.size % info.layers != 0 || layer_count == 0 ||
base_layer >= info.layers || layer_count > info.layers - base_layer || image == nullptr || base_layer >= info.layers || layer_count > info.layers - base_layer || image == nullptr ||
base_layer >= image->layers || layer_count > image->layers - base_layer) { base_layer >= image->layers || layer_count > image->layers - base_layer) {
@@ -218,12 +217,12 @@ void UploadRenderTargetLayers(GraphicContext* ctx, RenderTextureVulkanImage* ima
} }
void UploadRenderTarget(GraphicContext* ctx, RenderTextureVulkanImage* image, void UploadRenderTarget(GraphicContext* ctx, RenderTextureVulkanImage* image,
const RenderTargetInfo& info, bool refresh) { const RenderTargetInfo& info, bool refresh) {
UploadRenderTargetLayers(ctx, image, info, 0, info.layers, refresh); UploadRenderTargetLayers(ctx, image, info, 0, info.layers, refresh);
} }
RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTargetInfo& info, RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTargetInfo& info,
VulkanMemory* memory) { VulkanMemory* memory) {
auto* image = new RenderTextureVulkanImage; auto* image = new RenderTextureVulkanImage;
image->extent.width = info.width; image->extent.width = info.width;
image->extent.height = info.height; image->extent.height = info.height;
@@ -257,7 +256,7 @@ RenderTextureVulkanImage* CreateRenderTarget(GraphicContext* ctx, const RenderTa
} }
DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info, DepthStencilVulkanImage* CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info,
VulkanMemory* memory) { VulkanMemory* memory) {
VkImageCreateInfo create {}; VkImageCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; create.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create.imageType = VK_IMAGE_TYPE_2D; create.imageType = VK_IMAGE_TYPE_2D;
@@ -333,7 +332,7 @@ void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info) {
} }
VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info, VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info,
VulkanMemory* memory) { VulkanMemory* memory) {
auto* image = new VideoOutVulkanImage; auto* image = new VideoOutVulkanImage;
image->extent.width = info.width; image->extent.width = info.width;
image->extent.height = info.height; image->extent.height = info.height;
@@ -365,7 +364,7 @@ VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& inf
} }
void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const VideoOutInfo& info, void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const VideoOutInfo& info,
bool refresh) { bool refresh) {
if (info.compression != VideoOutCompression::Uncompressed) { if (info.compression != VideoOutCompression::Uncompressed) {
EXIT("TextureCache: compressed video-out guest upload is unsupported, " EXIT("TextureCache: compressed video-out guest upload is unsupported, "
"addr=0x%016" PRIx64 " metadata=0x%016" PRIx64 " dcc=0x%08" PRIx32 "\n", "addr=0x%016" PRIx64 " metadata=0x%016" PRIx64 " dcc=0x%08" PRIx32 "\n",
@@ -390,17 +389,17 @@ void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const Video
} }
GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d, GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d,
bool storage, VulkanMemory* memory) { bool storage, VulkanMemory* memory) {
if (memory == nullptr || memory->allocation != nullptr) { if (memory == nullptr || memory->allocation != nullptr) {
EXIT("TextureCache: invalid dummy texture memory slot, slot=%p allocation=%p storage=%d\n", EXIT("TextureCache: invalid dummy texture memory slot, slot=%p allocation=%p storage=%d\n",
static_cast<const void*>(memory), static_cast<const void*>(memory),
memory == nullptr ? nullptr : static_cast<const void*>(memory->allocation), storage); memory == nullptr ? nullptr : static_cast<const void*>(memory->allocation), storage);
} }
auto* image = storage ? static_cast<GpuTextureVulkanImage*>(new StorageTextureVulkanImage) auto* image = storage ? static_cast<GpuTextureVulkanImage*>(new StorageTextureVulkanImage)
: new TextureVulkanImage; : new TextureVulkanImage;
auto usage = storage ? TextureFormatUsage::Storage : TextureFormatUsage::Sampled; auto usage = storage ? TextureFormatUsage::Storage : TextureFormatUsage::Sampled;
auto layout = storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; auto layout = storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
auto owner = storage ? "DummyStorageTexture" : "DummySampledTexture"; auto owner = storage ? "DummyStorageTexture" : "DummySampledTexture";
auto params = MakeDummyTextureParams(uint_format, image_3d, usage, owner); auto params = MakeDummyTextureParams(uint_format, image_3d, usage, owner);
auto components = TextureCreateImage(ctx, image, memory, params); auto components = TextureCreateImage(ctx, image, memory, params);
+27 -27
View File
@@ -23,26 +23,26 @@ struct Image final: ImageInfo {
EXIT("dirty sampled image cannot be reassigned\n"); EXIT("dirty sampled image cannot be reassigned\n");
} }
static_cast<ImageInfo&>(*this) = value; static_cast<ImageInfo&>(*this) = value;
m_track_begin = address; m_track_begin = address;
m_track_end = address + size; m_track_end = address + size;
m_maybe_cpu_hash_valid = false; m_maybe_cpu_hash_valid = false;
return *this; return *this;
} }
void InvalidateCpuWrite(uint64_t vaddr, uint64_t size) { void InvalidateCpuWrite(uint64_t vaddr, uint64_t size) {
if (ImageRangeOverlaps(address, this->size, vaddr, size)) { if (ImageRangeOverlaps(address, this->size, vaddr, size)) {
m_cpu_dirty = true; m_cpu_dirty = true;
m_maybe_cpu_dirty = false; m_maybe_cpu_dirty = false;
m_maybe_cpu_hash_valid = false; m_maybe_cpu_hash_valid = false;
m_track_begin = m_track_end; m_track_begin = m_track_end;
} else if (ImagePageRangesOverlap(address, this->size, vaddr, size)) { } else if (ImagePageRangesOverlap(address, this->size, vaddr, size)) {
constexpr uint64_t page_mask = 4096 - 1; constexpr uint64_t page_mask = 4096 - 1;
if (vaddr + size <= address) { if (vaddr + size <= address) {
const auto next_page = (address + page_mask) & ~page_mask; const auto next_page = (address + page_mask) & ~page_mask;
m_track_begin = std::min(m_track_end, std::max(m_track_begin, next_page)); m_track_begin = std::min(m_track_end, std::max(m_track_begin, next_page));
} else if (vaddr >= address + this->size) { } else if (vaddr >= address + this->size) {
const auto page = (address + this->size) & ~page_mask; const auto page = (address + this->size) & ~page_mask;
m_track_end = std::max(m_track_begin, std::min(m_track_end, page)); m_track_end = std::max(m_track_begin, std::min(m_track_end, page));
} }
m_maybe_cpu_dirty = m_track_begin == m_track_end; m_maybe_cpu_dirty = m_track_begin == m_track_end;
} }
@@ -82,27 +82,27 @@ struct Image final: ImageInfo {
if (!IsCpuDirty()) { if (!IsCpuDirty()) {
EXIT("clean sampled image cannot complete a refresh\n"); EXIT("clean sampled image cannot complete a refresh\n");
} }
m_cpu_dirty = false; m_cpu_dirty = false;
m_maybe_cpu_dirty = false; m_maybe_cpu_dirty = false;
m_maybe_cpu_hash_valid = false; m_maybe_cpu_hash_valid = false;
m_track_begin = address; m_track_begin = address;
m_track_end = address + size; m_track_end = address + size;
} }
private: private:
bool m_cpu_dirty = false; bool m_cpu_dirty = false;
bool m_maybe_cpu_dirty = false; bool m_maybe_cpu_dirty = false;
bool m_maybe_cpu_hash_valid = false; bool m_maybe_cpu_hash_valid = false;
uint64_t m_track_begin = 0; uint64_t m_track_begin = 0;
uint64_t m_track_end = 0; uint64_t m_track_end = 0;
uint64_t m_maybe_cpu_hash = 0; uint64_t m_maybe_cpu_hash = 0;
}; };
namespace ImageOps { namespace ImageOps {
[[nodiscard]] GpuTextureVulkanImage* [[nodiscard]] GpuTextureVulkanImage* CreateTexture(GraphicContext* ctx, const ImageInfo& info,
CreateTexture(GraphicContext* ctx, const ImageInfo& info, bool storage, VulkanMemory* memory, bool storage, VulkanMemory* memory,
VkComponentMapping* components); VkComponentMapping* components);
void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info, void CreateTextureViews(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
bool storage, VkComponentMapping components); bool storage, VkComponentMapping components);
@@ -118,15 +118,15 @@ void UploadRenderTarget(GraphicContext* ctx, RenderTextureVulkanImage* image,
[[nodiscard]] DepthStencilVulkanImage* [[nodiscard]] DepthStencilVulkanImage*
CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info, VulkanMemory* memory); CreateDepthTarget(GraphicContext* ctx, const DepthTargetInfo& info, VulkanMemory* memory);
void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info); void ValidateVideoOut(GraphicContext* ctx, const VideoOutInfo& info);
[[nodiscard]] VideoOutVulkanImage* [[nodiscard]] VideoOutVulkanImage* CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info,
CreateVideoOut(GraphicContext* ctx, const VideoOutInfo& info, VulkanMemory* memory); VulkanMemory* memory);
void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const VideoOutInfo& info, void UploadVideoOut(GraphicContext* ctx, VideoOutVulkanImage* image, const VideoOutInfo& info,
bool refresh); bool refresh);
[[nodiscard]] GpuTextureVulkanImage* [[nodiscard]] GpuTextureVulkanImage* CreateDummyTexture(GraphicContext* ctx, bool uint_format,
CreateDummyTexture(GraphicContext* ctx, bool uint_format, bool image_3d, bool storage, bool image_3d, bool storage,
VulkanMemory* memory); VulkanMemory* memory);
void Destroy(GraphicContext* ctx, GpuTextureVulkanImage* image, VulkanMemory* memory); void Destroy(GraphicContext* ctx, GpuTextureVulkanImage* image, VulkanMemory* memory);
void Destroy(GraphicContext* ctx, RenderTextureVulkanImage* image, VulkanMemory* memory); void Destroy(GraphicContext* ctx, RenderTextureVulkanImage* image, VulkanMemory* memory);
+27 -34
View File
@@ -225,12 +225,7 @@ FindGuestDepthFormatPolicy(uint32_t guest_format) noexcept {
: info.format == policy->depth_attachment_format); : info.format == policy->depth_attachment_format);
} }
enum class VideoOutCompression : uint8_t { enum class VideoOutCompression : uint8_t { Uncompressed, Dcc256_256_0, Dcc256_64_64, Unsupported };
Uncompressed,
Dcc256_256_0,
Dcc256_64_64,
Unsupported
};
struct VideoOutInfo { struct VideoOutInfo {
uint64_t address = 0; uint64_t address = 0;
@@ -381,15 +376,16 @@ enum class BufferImageWrite : uint8_t {
enum class StorageBufferRebind : uint8_t { Reuse, RefreshFromBacking, Unsupported }; enum class StorageBufferRebind : uint8_t { Reuse, RefreshFromBacking, Unsupported };
enum class MetaImageOverlap : uint8_t { RetainSampled, RetireTarget, Unsupported }; enum class MetaImageOverlap : uint8_t { RetainSampled, RetireTarget, Unsupported };
[[nodiscard]] inline constexpr uint32_t SelectImageBackingBaseLevel(bool storage, [[nodiscard]] inline constexpr uint32_t SelectImageBackingBaseLevel(bool storage,
uint32_t view_base_level) { uint32_t view_base_level) {
// Storage descriptors select a per-mip view of one full allocation. Backing creation must not // Storage descriptors select a per-mip view of one full allocation. Backing creation must not
// depend on which view happens to be bound first. // depend on which view happens to be bound first.
return storage ? 0u : view_base_level; return storage ? 0u : view_base_level;
} }
[[nodiscard]] inline constexpr bool IsDepthUintTextureReinterpretation( [[nodiscard]] inline constexpr bool
VkFormat image_format, uint32_t guest_format, VkFormat view_format) noexcept { IsDepthUintTextureReinterpretation(VkFormat image_format, uint32_t guest_format,
VkFormat view_format) noexcept {
switch (image_format) { switch (image_format) {
case VK_FORMAT_D32_SFLOAT: case VK_FORMAT_D32_SFLOAT:
return guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) && return guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) &&
@@ -399,7 +395,7 @@ enum class MetaImageOverlap : uint8_t { RetainSampled, RetireTarget, Unsupported
} }
[[nodiscard]] inline constexpr bool NeedsStaticSampledArrayView(bool shader_array, [[nodiscard]] inline constexpr bool NeedsStaticSampledArrayView(bool shader_array,
bool dynamic_view_selected) { bool dynamic_view_selected) {
return shader_array && !dynamic_view_selected; return shader_array && !dynamic_view_selected;
} }
@@ -429,8 +425,8 @@ SelectStorageSampledViewShape(uint32_t type, uint32_t depth, uint32_t backing_la
} }
} }
[[nodiscard]] inline constexpr bool IsSupportedDisplayRenderTargetTileMode( [[nodiscard]] inline constexpr bool
uint32_t tile_mode) noexcept { IsSupportedDisplayRenderTargetTileMode(uint32_t tile_mode) noexcept {
return tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget); return tile_mode == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
} }
@@ -637,18 +633,16 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
} }
[[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsRgba16UintFloatReinterpretation(VkFormat cached,
VkFormat requested) noexcept { VkFormat requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT: return requested == VK_FORMAT_R16G16B16A16_UINT;
return requested == VK_FORMAT_R16G16B16A16_UINT; case VK_FORMAT_R16G16B16A16_UINT: return requested == VK_FORMAT_R16G16B16A16_SFLOAT;
case VK_FORMAT_R16G16B16A16_UINT:
return requested == VK_FORMAT_R16G16B16A16_SFLOAT;
default: return false; default: return false;
} }
} }
[[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(VkFormat cached, [[nodiscard]] inline bool IsRgba8UnormUintReinterpretation(VkFormat cached,
VkFormat requested) noexcept { VkFormat requested) noexcept {
switch (cached) { switch (cached) {
case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_UINT; case VK_FORMAT_R8G8B8A8_UNORM: return requested == VK_FORMAT_R8G8B8A8_UINT;
case VK_FORMAT_R8G8B8A8_UINT: return requested == VK_FORMAT_R8G8B8A8_UNORM; case VK_FORMAT_R8G8B8A8_UINT: return requested == VK_FORMAT_R8G8B8A8_UNORM;
@@ -656,7 +650,7 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
} }
} }
[[nodiscard]] inline bool IsSampledDepthExpansion(const ImageInfo& sampled, [[nodiscard]] inline bool IsSampledDepthExpansion(const ImageInfo& sampled,
const DepthTargetInfo& target) noexcept { const DepthTargetInfo& target) noexcept {
const bool array_expansion = const bool array_expansion =
sampled.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) && sampled.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) &&
@@ -664,14 +658,13 @@ SelectDepthTransitionSource(bool depth_load_clear, bool sampled_native_available
sampled.size == target.size * sampled.depth && sampled.width == target.width && sampled.size == target.size * sampled.depth && sampled.width == target.width &&
sampled.height == target.height && sampled.pitch == target.pitch; sampled.height == target.height && sampled.pitch == target.pitch;
return sampled.address == target.address && sampled.size > target.size && return sampled.address == target.address && sampled.size > target.size &&
sampled.format == target.guest_format && sampled.format == target.guest_format && target.format == VK_FORMAT_D32_SFLOAT &&
target.format == VK_FORMAT_D32_SFLOAT &&
target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && target.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
target.bytes_per_element == 4 && target.stencil_address == 0 && target.bytes_per_element == 4 && target.stencil_address == 0 &&
target.stencil_size == 0 && target.htile_address == 0 && target.htile_size == 0 && target.stencil_size == 0 && target.htile_address == 0 && target.htile_size == 0 &&
target.layers == 1 && array_expansion && target.layers == 1 && array_expansion && sampled.base_level == 0 &&
sampled.base_level == 0 && sampled.levels == 1 && sampled.view_levels == 1 && sampled.levels == 1 && sampled.view_levels == 1 && sampled.tile == target.tile_mode &&
sampled.tile == target.tile_mode && sampled.base_array == 0; sampled.base_array == 0;
} }
[[nodiscard]] inline StorageSampledOverlap [[nodiscard]] inline StorageSampledOverlap
@@ -776,8 +769,8 @@ ClassifyBufferImageWrite(uint64_t buffer_address, uint64_t buffer_size, uint64_t
[[nodiscard]] inline StorageBufferRebind [[nodiscard]] inline StorageBufferRebind
ClassifyStorageBufferRebind(bool buffer_overlap, bool cached_gpu_modified, ClassifyStorageBufferRebind(bool buffer_overlap, bool cached_gpu_modified,
bool cached_buffer_modified, bool tracker_gpu_modified, bool cached_buffer_modified, bool tracker_gpu_modified,
bool tracker_cpu_modified, bool coherent_guest_source) noexcept { bool tracker_cpu_modified, bool coherent_guest_source) noexcept {
if (cached_gpu_modified != tracker_gpu_modified || if (cached_gpu_modified != tracker_gpu_modified ||
(tracker_gpu_modified && tracker_cpu_modified)) { (tracker_gpu_modified && tracker_cpu_modified)) {
return StorageBufferRebind::Unsupported; return StorageBufferRebind::Unsupported;
@@ -832,13 +825,13 @@ ClassifyStorageBufferRebind(bool buffer_overlap, bool cached_gpu_modified,
// Mirrors storage -> depth-target binding transition. An inaccessible stencil aspect // Mirrors storage -> depth-target binding transition. An inaccessible stencil aspect
// does not require the otherwise necessary image content copy. // does not require the otherwise necessary image content copy.
[[nodiscard]] inline DepthOverlap ClassifyStorageDepthOverlap(const ImageInfo& storage, [[nodiscard]] inline DepthOverlap ClassifyStorageDepthOverlap(const ImageInfo& storage,
const DepthTargetInfo& depth) { const DepthTargetInfo& depth) {
const bool overlaps_depth = ImageRangeOverlaps(storage.address, storage.size, depth.address, const bool overlaps_depth =
depth.size); ImageRangeOverlaps(storage.address, storage.size, depth.address, depth.size);
const bool overlaps_stencil = depth.stencil_address != 0 && const bool overlaps_stencil =
ImageRangeOverlaps(storage.address, storage.size, depth.stencil_address != 0 && ImageRangeOverlaps(storage.address, storage.size,
depth.stencil_address, depth.stencil_size); depth.stencil_address, depth.stencil_size);
if (!overlaps_depth && !overlaps_stencil) { if (!overlaps_depth && !overlaps_stencil) {
return DepthOverlap::None; return DepthOverlap::None;
} }
@@ -857,7 +850,7 @@ ClassifyRenderTargetOverlap(const ImageInfo& sampled, bool sampled_gpu_modified,
return RenderTargetOverlap::None; return RenderTargetOverlap::None;
} }
return !sampled_gpu_modified && same_context ? RenderTargetOverlap::RetireSampled return !sampled_gpu_modified && same_context ? RenderTargetOverlap::RetireSampled
: RenderTargetOverlap::Unsupported; : RenderTargetOverlap::Unsupported;
} }
[[nodiscard]] inline RenderTargetOverlap [[nodiscard]] inline RenderTargetOverlap
+22 -24
View File
@@ -125,11 +125,11 @@ VkImageView TextureCache::GetRenderTargetAttachmentView(GraphicContext*
static_cast<int>(image->format), static_cast<int>(format), level); static_cast<int>(image->format), static_cast<int>(format), level);
} }
return GetImageView( return GetImageView(ctx, image,
ctx, image, {format,
{format, layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY, layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY,
VK_IMAGE_ASPECT_COLOR_BIT, level, 1, base_layer, layer_count, DstSel(4, 5, 6, 7), VK_IMAGE_ASPECT_COLOR_BIT, level, 1, base_layer, layer_count,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT}); DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT});
} }
VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx, VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext* ctx,
@@ -151,9 +151,9 @@ VkImageView TextureCache::GetDepthTargetAttachmentView(GraphicContext*
VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image, VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
const ImageViewInfo& info) { const ImageViewInfo& info) {
const bool supported_type = info.type == VK_IMAGE_VIEW_TYPE_2D || const bool supported_type = info.type == VK_IMAGE_VIEW_TYPE_2D ||
info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY || info.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
info.type == VK_IMAGE_VIEW_TYPE_3D; info.type == VK_IMAGE_VIEW_TYPE_3D;
const bool supported_usage = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT || const bool supported_usage = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT ||
info.usage == VK_IMAGE_USAGE_STORAGE_BIT || info.usage == VK_IMAGE_USAGE_STORAGE_BIT ||
info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT || info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ||
@@ -189,14 +189,14 @@ VkImageView TextureCache::GetImageView(GraphicContext* ctx, VulkanImage* image,
usage.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; usage.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
usage.usage = info.usage; usage.usage = info.usage;
VkImageViewCreateInfo create {}; VkImageViewCreateInfo create {};
create.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; create.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
create.pNext = &usage; create.pNext = &usage;
create.image = image->image; create.image = image->image;
create.viewType = info.type; create.viewType = info.type;
create.format = info.format; create.format = info.format;
create.components = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT create.components = info.usage == VK_IMAGE_USAGE_SAMPLED_BIT
? TextureGetComponentMapping(info.swizzle) ? TextureGetComponentMapping(info.swizzle)
: VkComponentMapping {}; : VkComponentMapping {};
create.subresourceRange.aspectMask = info.aspect; create.subresourceRange.aspectMask = info.aspect;
create.subresourceRange.baseMipLevel = info.base_level; create.subresourceRange.baseMipLevel = info.base_level;
create.subresourceRange.levelCount = info.level_count; create.subresourceRange.levelCount = info.level_count;
@@ -239,10 +239,10 @@ VkImageView TextureCache::GetDepthTargetSampledView(GraphicContext* ctx
} }
VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image, VkImageView TextureCache::GetSampledColorView(GraphicContext* ctx, VulkanImage* image,
VkFormat view_format, uint32_t swizzle, VkFormat view_format, uint32_t swizzle,
uint32_t base_level, uint32_t level_count, uint32_t base_level, uint32_t level_count,
VkImageViewType type, uint32_t base_layer, VkImageViewType type, uint32_t base_layer,
uint32_t layer_count) { uint32_t layer_count) {
if (ctx == nullptr || image == nullptr || image->image == nullptr || if (ctx == nullptr || image == nullptr || image->image == nullptr ||
view_format == VK_FORMAT_UNDEFINED || base_level >= 16 || view_format == VK_FORMAT_UNDEFINED || base_level >= 16 ||
(type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) || (type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) ||
@@ -309,8 +309,7 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count, {view_format, type, VK_IMAGE_ASPECT_COLOR_BIT, base_level, level_count,
base_layer, layer_count, DstSel(4, 5, 6, 7), base_layer, layer_count, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT});
VK_IMAGE_USAGE_STORAGE_BIT});
} }
VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx, VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx,
@@ -362,8 +361,7 @@ VkImageView TextureCache::GetStorageTextureStorageView(GraphicContext*
} }
return GetImageView(ctx, image, return GetImageView(ctx, image,
{image->format, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, {image->format, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT,
base_level, 1, 0, 1, DstSel(4, 5, 6, 7), base_level, 1, 0, 1, DstSel(4, 5, 6, 7), VK_IMAGE_USAGE_STORAGE_BIT});
VK_IMAGE_USAGE_STORAGE_BIT});
} }
} // namespace Libs::Graphics } // namespace Libs::Graphics
+6 -10
View File
@@ -18,8 +18,7 @@ namespace Libs::Graphics {
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) || format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float); format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
return swizzle == DstSel(4, 5, 6, 7) || return swizzle == DstSel(4, 5, 6, 7) ||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || (single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 4, 4, 4))) || swizzle == DstSel(4, 4, 4, 4))) ||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32UInt) && (format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32UInt) &&
swizzle == DstSel(4, 5, 0, 1)) || swizzle == DstSel(4, 5, 0, 1)) ||
@@ -104,9 +103,8 @@ namespace Libs::Graphics {
return true; return true;
} }
[[nodiscard]] inline bool IsSupportedSampledColorView(VkFormat image_format, [[nodiscard]] inline bool IsSupportedSampledColorView(VkFormat image_format, VkFormat view_format,
VkFormat view_format, uint32_t swizzle) noexcept {
uint32_t swizzle) noexcept {
if (!IsValidSampledColorSwizzle(swizzle)) { if (!IsValidSampledColorSwizzle(swizzle)) {
return false; return false;
} }
@@ -118,8 +116,7 @@ namespace Libs::Graphics {
swizzle == DstSel(4, 5, 6, 7)) { swizzle == DstSel(4, 5, 6, 7)) {
return true; return true;
} }
return IsBgraToRgbaSampledView(image_format, view_format) && return IsBgraToRgbaSampledView(image_format, view_format) && swizzle == DstSel(6, 5, 4, 7);
swizzle == DstSel(6, 5, 4, 7);
} }
[[nodiscard]] inline uint32_t SelectSampledColorView(VkFormat image_format, VkFormat view_format, [[nodiscard]] inline uint32_t SelectSampledColorView(VkFormat image_format, VkFormat view_format,
@@ -177,8 +174,7 @@ IsSupportedSampledDepthUintResource(const ShaderRecompiler::IR::ImageResource& r
view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT; view_format == VK_FORMAT_R16_SFLOAT || view_format == VK_FORMAT_R32_SFLOAT;
const bool swizzle_ok = const bool swizzle_ok =
swizzle == DstSel(4, 5, 6, 7) || swizzle == DstSel(4, 5, 6, 7) ||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || (single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 0, 0, 1) ||
swizzle == DstSel(4, 4, 4, 4))) || swizzle == DstSel(4, 4, 4, 4))) ||
(view_format == VK_FORMAT_R32G32_UINT && swizzle == DstSel(4, 5, 0, 1)) || (view_format == VK_FORMAT_R32G32_UINT && swizzle == DstSel(4, 5, 0, 1)) ||
((view_format == VK_FORMAT_R8G8B8A8_UNORM || view_format == VK_FORMAT_R8G8B8A8_UINT) && ((view_format == VK_FORMAT_R8G8B8A8_UNORM || view_format == VK_FORMAT_R8G8B8A8_UINT) &&
@@ -217,7 +213,7 @@ ValidateStorageImageResource(const ShaderRecompiler::IR::ImageResource& resource
namespace ImageViewOps { namespace ImageViewOps {
[[nodiscard]] VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept; [[nodiscard]] VkImageAspectFlags DepthAspectMask(VkFormat format) noexcept;
[[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format); [[nodiscard]] bool FormatSupportsStorage(GraphicContext* ctx, VkFormat format);
void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image); void CreateRenderTargetViews(GraphicContext* ctx, RenderTextureVulkanImage* image);
void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image); void CreateDepthViews(GraphicContext* ctx, DepthStencilVulkanImage* image);
@@ -15,7 +15,8 @@ namespace Libs::Graphics {
// Sparse two-level lookup for texture-cache page ownership. // Sparse two-level lookup for texture-cache page ownership.
// Entries are selected by guest page number; queries never allocate L1 buckets. // Entries are selected by guest page number; queries never allocate L1 buckets.
template <typename EntryT, size_t PageBits = 20, size_t AddressSpaceBits = 40, size_t FirstLevelBits = 10> template <typename EntryT, size_t PageBits = 20, size_t AddressSpaceBits = 40,
size_t FirstLevelBits = 10>
class MultiLevelPageTable final { class MultiLevelPageTable final {
public: public:
using Entry = EntryT; using Entry = EntryT;
@@ -24,14 +25,14 @@ public:
static_assert(PageBits < AddressSpaceBits); static_assert(PageBits < AddressSpaceBits);
static_assert(FirstLevelBits > 0 && FirstLevelBits <= AddressSpaceBits - PageBits); static_assert(FirstLevelBits > 0 && FirstLevelBits <= AddressSpaceBits - PageBits);
static constexpr size_t kPageBits = PageBits; static constexpr size_t kPageBits = PageBits;
static constexpr size_t kAddressSpaceBits = AddressSpaceBits; static constexpr size_t kAddressSpaceBits = AddressSpaceBits;
static constexpr size_t kFirstLevelBits = FirstLevelBits; static constexpr size_t kFirstLevelBits = FirstLevelBits;
static constexpr size_t kSecondLevelBits = AddressSpaceBits - FirstLevelBits - PageBits; static constexpr size_t kSecondLevelBits = AddressSpaceBits - FirstLevelBits - PageBits;
static constexpr size_t kFirstLevelEntries = size_t{1} << FirstLevelBits; static constexpr size_t kFirstLevelEntries = size_t {1} << FirstLevelBits;
static constexpr size_t kBucketEntries = size_t{1} << kSecondLevelBits; static constexpr size_t kBucketEntries = size_t {1} << kSecondLevelBits;
static constexpr size_t kPageCount = size_t{1} << (AddressSpaceBits - PageBits); static constexpr size_t kPageCount = size_t {1} << (AddressSpaceBits - PageBits);
static constexpr uint64_t kAddressSpaceSize = uint64_t{1} << AddressSpaceBits; static constexpr uint64_t kAddressSpaceSize = uint64_t {1} << AddressSpaceBits;
struct PageRange final { struct PageRange final {
size_t first = 0; size_t first = 0;
@@ -74,12 +75,13 @@ public:
// Returns the half-open page interval touched by a non-empty byte range. // Returns the half-open page interval touched by a non-empty byte range.
// An end exactly at 2^AddressSpaceBits is valid; wrapping or crossing it is not. // An end exactly at 2^AddressSpaceBits is valid; wrapping or crossing it is not.
[[nodiscard]] static constexpr bool TryGetPageRange(uint64_t address, uint64_t size, PageRange& range) { [[nodiscard]] static constexpr bool TryGetPageRange(uint64_t address, uint64_t size,
PageRange& range) {
if (size == 0 || address >= kAddressSpaceSize || size > kAddressSpaceSize - address) { if (size == 0 || address >= kAddressSpaceSize || size > kAddressSpaceSize - address) {
return false; return false;
} }
const uint64_t end = address + size; const uint64_t end = address + size;
range.first = static_cast<size_t>(address >> PageBits); range.first = static_cast<size_t>(address >> PageBits);
range.last_exclusive = static_cast<size_t>(((end - 1) >> PageBits) + 1); range.last_exclusive = static_cast<size_t>(((end - 1) >> PageBits) + 1);
return true; return true;
} }
@@ -89,8 +91,12 @@ public:
private: private:
using Bucket = std::array<Entry, kBucketEntries>; using Bucket = std::array<Entry, kBucketEntries>;
[[nodiscard]] static constexpr size_t FirstLevelIndex(size_t page) { return page >> kSecondLevelBits; } [[nodiscard]] static constexpr size_t FirstLevelIndex(size_t page) {
[[nodiscard]] static constexpr size_t SecondLevelIndex(size_t page) { return page & (kBucketEntries - 1); } return page >> kSecondLevelBits;
}
[[nodiscard]] static constexpr size_t SecondLevelIndex(size_t page) {
return page & (kBucketEntries - 1);
}
std::vector<std::unique_ptr<Bucket>> m_first_level; std::vector<std::unique_ptr<Bucket>> m_first_level;
size_t m_allocated_buckets = 0; size_t m_allocated_buckets = 0;
@@ -151,8 +157,8 @@ public:
if (registration == m_registrations.end()) { if (registration == m_registrations.end()) {
return false; return false;
} }
const auto coarse_pages = CollectPages<20>(registration->ranges); const auto coarse_pages = CollectPages<20>(registration->ranges);
const auto tracking_pages = CollectPages<12>(registration->ranges); const auto tracking_pages = CollectPages<12>(registration->ranges);
const Registration* registration_ptr = &*registration; const Registration* registration_ptr = &*registration;
if (!HasAllMemberships(m_coarse_pages, coarse_pages, registration_ptr) || if (!HasAllMemberships(m_coarse_pages, coarse_pages, registration_ptr) ||
!HasAllMemberships(m_tracking_pages, tracking_pages, registration_ptr)) { !HasAllMemberships(m_tracking_pages, tracking_pages, registration_ptr)) {
@@ -179,7 +185,8 @@ public:
} }
template <typename Predicate> template <typename Predicate>
[[nodiscard]] std::vector<OwnerT> Query(uint64_t address, uint64_t size, Predicate&& predicate) const { [[nodiscard]] std::vector<OwnerT> Query(uint64_t address, uint64_t size,
Predicate&& predicate) const {
return QueryImpl(address, size, true, std::forward<Predicate>(predicate)); return QueryImpl(address, size, true, std::forward<Predicate>(predicate));
} }
@@ -190,7 +197,8 @@ public:
} }
template <typename Predicate> template <typename Predicate>
[[nodiscard]] std::vector<OwnerT> QueryCandidates(uint64_t address, uint64_t size, Predicate&& predicate) const { [[nodiscard]] std::vector<OwnerT> QueryCandidates(uint64_t address, uint64_t size,
Predicate&& predicate) const {
return QueryImpl(address, size, false, std::forward<Predicate>(predicate)); return QueryImpl(address, size, false, std::forward<Predicate>(predicate));
} }
@@ -206,9 +214,9 @@ public:
private: private:
template <typename Predicate> template <typename Predicate>
[[nodiscard]] std::vector<OwnerT> QueryImpl(uint64_t address, uint64_t size, bool strict_bytes, [[nodiscard]] std::vector<OwnerT> QueryImpl(uint64_t address, uint64_t size, bool strict_bytes,
Predicate&& predicate) const { Predicate&& predicate) const {
typename CoarseTable::PageRange coarse_range{}; typename CoarseTable::PageRange coarse_range {};
typename TrackingTable::PageRange tracking_range{}; typename TrackingTable::PageRange tracking_range {};
if (!CoarseTable::TryGetPageRange(address, size, coarse_range) || if (!CoarseTable::TryGetPageRange(address, size, coarse_range) ||
!TrackingTable::TryGetPageRange(address, size, tracking_range)) { !TrackingTable::TryGetPageRange(address, size, tracking_range)) {
return {}; return {};
@@ -222,7 +230,8 @@ private:
std::vector<OwnerT> result; std::vector<OwnerT> result;
for (const Registration* registration: candidates) { for (const Registration* registration: candidates) {
if ((!strict_bytes || Overlaps(registration->ranges, address, size)) && if ((!strict_bytes || Overlaps(registration->ranges, address, size)) &&
HasTrackingMembership(registration, tracking_range) && predicate(registration->owner)) { HasTrackingMembership(registration, tracking_range) &&
predicate(registration->owner)) {
result.push_back(registration->owner); result.push_back(registration->owner);
} }
} }
@@ -248,20 +257,22 @@ private:
[[nodiscard]] static std::vector<ByteRange> Normalize(const std::vector<ByteRange>& ranges) { [[nodiscard]] static std::vector<ByteRange> Normalize(const std::vector<ByteRange>& ranges) {
std::vector<ByteRange> sorted; std::vector<ByteRange> sorted;
for (const auto& range: ranges) { for (const auto& range: ranges) {
typename CoarseTable::PageRange ignored{}; typename CoarseTable::PageRange ignored {};
if (!CoarseTable::TryGetPageRange(range.address, range.size, ignored)) { if (!CoarseTable::TryGetPageRange(range.address, range.size, ignored)) {
return {}; return {};
} }
sorted.push_back(range); sorted.push_back(range);
} }
std::sort(sorted.begin(), sorted.end(), std::sort(sorted.begin(), sorted.end(), [](const ByteRange& lhs, const ByteRange& rhs) {
[](const ByteRange& lhs, const ByteRange& rhs) { return lhs.address < rhs.address; }); return lhs.address < rhs.address;
});
std::vector<ByteRange> merged; std::vector<ByteRange> merged;
for (const auto& range: sorted) { for (const auto& range: sorted) {
if (merged.empty() || range.address > merged.back().address + merged.back().size) { if (merged.empty() || range.address > merged.back().address + merged.back().size) {
merged.push_back(range); merged.push_back(range);
} else { } else {
const uint64_t end = std::max(merged.back().address + merged.back().size, range.address + range.size); const uint64_t end = std::max(merged.back().address + merged.back().size,
range.address + range.size);
merged.back().size = end - merged.back().address; merged.back().size = end - merged.back().address;
} }
} }
@@ -284,29 +295,33 @@ private:
} }
template <typename Table> template <typename Table>
[[nodiscard]] static bool HasAllMemberships(const Table& table, const std::vector<size_t>& pages, [[nodiscard]] static bool HasAllMemberships(const Table& table,
const Registration* registration) { const std::vector<size_t>& pages,
const Registration* registration) {
for (const size_t page: pages) { for (const size_t page: pages) {
const auto* owners = table.Find(page); const auto* owners = table.Find(page);
if (owners == nullptr || std::find(owners->begin(), owners->end(), registration) == owners->end()) { if (owners == nullptr ||
std::find(owners->begin(), owners->end(), registration) == owners->end()) {
return false; return false;
} }
} }
return true; return true;
} }
[[nodiscard]] bool HasTrackingMembership(const Registration* registration, [[nodiscard]] bool HasTrackingMembership(const Registration* registration,
const typename TrackingTable::PageRange& range) const { const typename TrackingTable::PageRange& range) const {
for (size_t page = range.first; page < range.last_exclusive; ++page) { for (size_t page = range.first; page < range.last_exclusive; ++page) {
const auto* owners = m_tracking_pages.Find(page); const auto* owners = m_tracking_pages.Find(page);
if (owners != nullptr && std::find(owners->begin(), owners->end(), registration) != owners->end()) { if (owners != nullptr &&
std::find(owners->begin(), owners->end(), registration) != owners->end()) {
return true; return true;
} }
} }
return false; return false;
} }
[[nodiscard]] static bool Overlaps(const std::vector<ByteRange>& ranges, uint64_t address, uint64_t size) { [[nodiscard]] static bool Overlaps(const std::vector<ByteRange>& ranges, uint64_t address,
uint64_t size) {
const uint64_t end = address + size; const uint64_t end = address + size;
return std::any_of(ranges.begin(), ranges.end(), [&](const ByteRange& range) { return std::any_of(ranges.begin(), ranges.end(), [&](const ByteRange& range) {
return range.address < end && address < range.address + range.size; return range.address < end && address < range.address + range.size;
@@ -314,26 +329,28 @@ private:
} }
static void AppendUnique(MembershipList& destination, const MembershipList& source) { static void AppendUnique(MembershipList& destination, const MembershipList& source) {
for (const Registration* registration: source) { for (const Registration* registration: source) {
if (std::find(destination.begin(), destination.end(), registration) == destination.end()) { if (std::find(destination.begin(), destination.end(), registration) ==
destination.end()) {
destination.push_back(registration); destination.push_back(registration);
} }
} }
} }
[[nodiscard]] static std::vector<ByteRange> CoalesceTrackingPages(const std::vector<size_t>& pages) { [[nodiscard]] static std::vector<ByteRange>
CoalesceTrackingPages(const std::vector<size_t>& pages) {
std::vector<ByteRange> result; std::vector<ByteRange> result;
for (const size_t page: pages) { for (const size_t page: pages) {
const uint64_t address = static_cast<uint64_t>(page) << 12; const uint64_t address = static_cast<uint64_t>(page) << 12;
if (!result.empty() && result.back().address + result.back().size == address) { if (!result.empty() && result.back().address + result.back().size == address) {
result.back().size += uint64_t{1} << 12; result.back().size += uint64_t {1} << 12;
} else { } else {
result.push_back({address, uint64_t{1} << 12}); result.push_back({address, uint64_t {1} << 12});
} }
} }
return result; return result;
} }
CoarseTable m_coarse_pages; CoarseTable m_coarse_pages;
TrackingTable m_tracking_pages; TrackingTable m_tracking_pages;
std::list<Registration> m_registrations; std::list<Registration> m_registrations;
}; };
@@ -268,7 +268,7 @@ static bool TryConsumeComputeMetaClear(const ShaderComputeInputInfo& input, cons
} }
if (resource.written || !resource.read || resource.atomic || descriptor.Base48() == 0 || if (resource.written || !resource.read || resource.atomic || descriptor.Base48() == 0 ||
descriptor_size == 0 || descriptor_size == 0 ||
cache->QueryRegion(descriptor.Base48(), descriptor_size).metadata_pages) { cache->QueryRegion(descriptor.Base48(), descriptor_size).metadata_pages) {
EXIT("unsupported HTile clear side-buffer access\n"); EXIT("unsupported HTile clear side-buffer access\n");
} }
g_render_ctx->GetBufferCache()->ValidateGpuAccess(descriptor.Base48(), descriptor_size, g_render_ctx->GetBufferCache()->ValidateGpuAccess(descriptor.Base48(), descriptor_size,
+10 -10
View File
@@ -1,3 +1,5 @@
#include "graphics/host_gpu/renderer/renderDraw.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common.h" #include "common/common.h"
#include "common/emulatorConfig.h" #include "common/emulatorConfig.h"
@@ -20,7 +22,6 @@
#include "graphics/host_gpu/renderer/pipelineCache.h" #include "graphics/host_gpu/renderer/pipelineCache.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/renderer/renderDraw.h"
#include "graphics/host_gpu/renderer/renderInternal.h" #include "graphics/host_gpu/renderer/renderInternal.h"
#include "graphics/host_gpu/renderer/renderVertex.h" #include "graphics/host_gpu/renderer/renderVertex.h"
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h" #include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
@@ -823,9 +824,9 @@ static void BindDrawIndexBuffer(CommandBuffer* buffer, VkCommandBuffer vk_buffer
VkDeviceSize index_offset = 0; VkDeviceSize index_offset = 0;
if (source.host_data != nullptr) { if (source.host_data != nullptr) {
VkDeviceSize range = 0; VkDeviceSize range = 0;
if (!g_render_ctx->GetBufferCache()->UploadHostData( if (!g_render_ctx->GetBufferCache()->UploadHostData(buffer, g_render_ctx->GetGraphicCtx(),
buffer, g_render_ctx->GetGraphicCtx(), source.host_data, source.size, 16, source.host_data, source.size, 16,
&index_buffer, &index_offset, &range)) { &index_buffer, &index_offset, &range)) {
EXIT("failed to upload host index buffer\n"); EXIT("failed to upload host index buffer\n");
} }
} else { } else {
@@ -1126,9 +1127,9 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
instance_count = 1; instance_count = 1;
} }
const DrawCallInfo draw {"DrawIndex", CommandBufferDebugOp::DrawIndex, const DrawCallInfo draw {"DrawIndex", CommandBufferDebugOp::DrawIndex,
index_count, flags, index_count, flags,
instance_count, first_instance}; instance_count, first_instance};
std::vector<uint16_t> expanded_indices; std::vector<uint16_t> expanded_indices;
if (expand_index8_to_u16) { if (expand_index8_to_u16) {
EXIT_NOT_IMPLEMENTED(index_addr == nullptr); EXIT_NOT_IMPLEMENTED(index_addr == nullptr);
@@ -1144,9 +1145,8 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
index_source.address = reinterpret_cast<uint64_t>(index_addr); index_source.address = reinterpret_cast<uint64_t>(index_addr);
index_source.host_data = index_source.host_data =
expanded_indices.empty() ? nullptr : static_cast<const void*>(expanded_indices.data()); expanded_indices.empty() ? nullptr : static_cast<const void*>(expanded_indices.data());
index_source.size = expanded_indices.empty() index_source.size =
? index_size expanded_indices.empty() ? index_size : expanded_indices.size() * sizeof(uint16_t);
: expanded_indices.size() * sizeof(uint16_t);
index_source.type = index_type; index_source.type = index_type;
DrawRenderState state {}; DrawRenderState state {};
@@ -217,8 +217,7 @@ void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, ui
Common::LockGuard lock(g_render_ctx->GetMutex()); Common::LockGuard lock(g_render_ctx->GetMutex());
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
auto* native = auto* native = g_render_ctx->GetTextureCache()->FindDepthTargetByRange(buffer, vaddr, size);
g_render_ctx->GetTextureCache()->FindDepthTargetByRange(buffer, vaddr, size);
if (native == nullptr) { if (native == nullptr) {
EXIT("depth-target barrier range has no cached image\n"); EXIT("depth-target barrier range has no cached image\n");
} }
@@ -66,15 +66,18 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
auto to_vk_address_mode = [](uint8_t clamp) { auto to_vk_address_mode = [](uint8_t clamp) {
switch (static_cast<Prospero::SamplerClampMode>(clamp)) { switch (static_cast<Prospero::SamplerClampMode>(clamp)) {
case Prospero::SamplerClampMode::kWrap: return VK_SAMPLER_ADDRESS_MODE_REPEAT; case Prospero::SamplerClampMode::kWrap: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case Prospero::SamplerClampMode::kMirror: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; case Prospero::SamplerClampMode::kMirror:
case Prospero::SamplerClampMode::kClampLastTexel: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case Prospero::SamplerClampMode::kClampLastTexel:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case Prospero::SamplerClampMode::kMirrorOnceLastTexel: case Prospero::SamplerClampMode::kMirrorOnceLastTexel:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
case Prospero::SamplerClampMode::kClampHalfBorder: case Prospero::SamplerClampMode::kClampHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case Prospero::SamplerClampMode::kMirrorOnceHalfBorder: case Prospero::SamplerClampMode::kMirrorOnceHalfBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
case Prospero::SamplerClampMode::kClampBorder: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; case Prospero::SamplerClampMode::kClampBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case Prospero::SamplerClampMode::kMirrorOnceBorder: case Prospero::SamplerClampMode::kMirrorOnceBorder:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default: EXIT("unknown clamp: %u\n", clamp); default: EXIT("unknown clamp: %u\n", clamp);
@@ -87,8 +90,12 @@ VkSampler SamplerCache::GetSampler(const ShaderSamplerResource& r) {
case Prospero::SamplerBorderColor::kTransBlack: case Prospero::SamplerBorderColor::kTransBlack:
border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; border = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
break; break;
case Prospero::SamplerBorderColor::kOpaqueBlack: border = VK_BORDER_COLOR_INT_OPAQUE_BLACK; break; case Prospero::SamplerBorderColor::kOpaqueBlack:
case Prospero::SamplerBorderColor::kOpaqueWhite: border = VK_BORDER_COLOR_INT_OPAQUE_WHITE; break; border = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
break;
case Prospero::SamplerBorderColor::kOpaqueWhite:
border = VK_BORDER_COLOR_INT_OPAQUE_WHITE;
break;
case Prospero::SamplerBorderColor::kFromTable: case Prospero::SamplerBorderColor::kFromTable:
LOGF( LOGF(
"temporary: approximating table border color as transparent black, index = %" PRIu16 "temporary: approximating table border color as transparent black, index = %" PRIu16
@@ -2,8 +2,8 @@
#include "common/assert.h" #include "common/assert.h"
#include "graphics/host_gpu/renderer/descriptorCache.h" #include "graphics/host_gpu/renderer/descriptorCache.h"
#include "graphics/shader/shaderBindings.h"
#include "graphics/shader/shader.h" #include "graphics/shader/shader.h"
#include "graphics/shader/shaderBindings.h"
#include <cstring> #include <cstring>
+1 -1
View File
@@ -22,7 +22,7 @@
namespace Libs::Graphics { namespace Libs::Graphics {
//IDK: maybe we can remove it? // IDK: maybe we can remove it?
constexpr uint32_t kTemporaryPs5BufferFormat121 = 121u; constexpr uint32_t kTemporaryPs5BufferFormat121 = 121u;
static bool NarrowInputFormat(VkFormat* format, uint32_t* size, uint32_t used_components) { static bool NarrowInputFormat(VkFormat* format, uint32_t* size, uint32_t used_components) {
+12 -14
View File
@@ -30,24 +30,22 @@ void HostStreamBuffer::EnsureBuffer(GraphicContext* ctx) {
return; return;
} }
KYTY_PROFILER_BLOCK("HostStreamBuffer::create"); KYTY_PROFILER_BLOCK("HostStreamBuffer::create");
m_ctx = ctx; m_ctx = ctx;
m_buffer = std::make_unique<VulkanBuffer>(); m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT; VK_BUFFER_USAGE_TRANSFER_DST_BIT;
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT; VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get()); VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get());
VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped); VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped);
const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1; const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1;
LOGF("HostStreamBuffer: created serial=%" PRIu64 " capacity=%" PRIu64 "\n", count, LOGF("HostStreamBuffer: created serial=%" PRIu64 " capacity=%" PRIu64 "\n", count, CAPACITY);
CAPACITY);
} }
bool HostStreamBuffer::Copy(GraphicContext* ctx, const void* src, uint64_t size, bool HostStreamBuffer::Copy(GraphicContext* ctx, const void* src, uint64_t size, uint64_t alignment,
uint64_t alignment, VulkanBuffer** out_buffer, uint64_t* out_offset, VulkanBuffer** out_buffer, uint64_t* out_offset, uint64_t* out_range) {
uint64_t* out_range) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
if (ctx == nullptr || src == nullptr || out_buffer == nullptr || out_offset == nullptr || if (ctx == nullptr || src == nullptr || out_buffer == nullptr || out_offset == nullptr ||
out_range == nullptr) { out_range == nullptr) {
@@ -69,10 +67,10 @@ bool HostStreamBuffer::Copy(GraphicContext* ctx, const void* src, uint64_t size,
} }
EnsureBuffer(ctx); EnsureBuffer(ctx);
std::memcpy(static_cast<uint8_t*>(m_mapped) + offset, src, static_cast<size_t>(size)); std::memcpy(static_cast<uint8_t*>(m_mapped) + offset, src, static_cast<size_t>(size));
m_offset = offset + size; m_offset = offset + size;
*out_buffer = m_buffer.get(); *out_buffer = m_buffer.get();
*out_offset = offset; *out_offset = offset;
*out_range = size; *out_range = size;
return true; return true;
} }
@@ -22,11 +22,10 @@ public:
~HostStreamBuffer(); ~HostStreamBuffer();
KYTY_CLASS_NO_COPY(HostStreamBuffer); KYTY_CLASS_NO_COPY(HostStreamBuffer);
[[nodiscard]] bool Copy(GraphicContext* ctx, const void* src, uint64_t size, [[nodiscard]] bool Copy(GraphicContext* ctx, const void* src, uint64_t size, uint64_t alignment,
uint64_t alignment, VulkanBuffer** out_buffer, uint64_t* out_offset, VulkanBuffer** out_buffer, uint64_t* out_offset, uint64_t* out_range);
uint64_t* out_range); void Reset() noexcept;
void Reset() noexcept; void Release() noexcept;
void Release() noexcept;
private: private:
void EnsureBuffer(GraphicContext* ctx); void EnsureBuffer(GraphicContext* ctx);
@@ -36,11 +35,11 @@ private:
// replaced by a single 64 MiB scheduler-watched ring; the BufferCache seam stays fixed. // replaced by a single 64 MiB scheduler-watched ring; the BufferCache seam stays fixed.
static constexpr uint64_t CAPACITY = 16ull * 1024ull * 1024ull; static constexpr uint64_t CAPACITY = 16ull * 1024ull * 1024ull;
mutable std::mutex m_mutex; mutable std::mutex m_mutex;
GraphicContext* m_ctx = nullptr; GraphicContext* m_ctx = nullptr;
std::unique_ptr<VulkanBuffer> m_buffer; std::unique_ptr<VulkanBuffer> m_buffer;
void* m_mapped = nullptr; void* m_mapped = nullptr;
uint64_t m_offset = 0; uint64_t m_offset = 0;
}; };
} // namespace Libs::Graphics } // namespace Libs::Graphics
+33 -40
View File
@@ -1,3 +1,5 @@
#include "graphics/host_gpu/renderer/sync.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common.h" #include "common/common.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@@ -7,7 +9,6 @@
#include "graphics/host_gpu/renderer/bufferCache.h" #include "graphics/host_gpu/renderer/bufferCache.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/renderer/sync.h"
#include "graphics/presentation/displayBuffer.h" #include "graphics/presentation/displayBuffer.h"
#include "kernel/eventQueue.h" #include "kernel/eventQueue.h"
#include "kernel/pthread.h" #include "kernel/pthread.h"
@@ -82,8 +83,8 @@ void TriggerEopEvent(uint32_t context_id) {
g_render_ctx->TriggerEopEvent(context_id); g_render_ctx->TriggerEopEvent(context_id);
} }
void WriteAtEndOfPipe32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipe32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr,
uint32_t* dst_gpu_addr, uint32_t value) { uint32_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -93,9 +94,8 @@ void WriteAtEndOfPipe32(uint64_t submit_id, CommandBuffer* buffer,
0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr)); 0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr));
} }
void WriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr,
uint32_t* dst_gpu_addr, uint32_t dw_offset, uint32_t dw_offset, uint32_t dw_num) {
uint32_t dw_num) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -105,8 +105,8 @@ void WriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer,
dw_offset, dw_num, 0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr)); dw_offset, dw_num, 0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr));
} }
void WriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr,
uint64_t* dst_gpu_addr, uint64_t value) { uint64_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -117,8 +117,8 @@ void WriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer,
reinterpret_cast<uint64_t>(dst_gpu_addr)); reinterpret_cast<uint64_t>(dst_gpu_addr));
} }
void WriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr,
uint64_t* dst_gpu_addr, uint64_t value) { uint64_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -132,10 +132,8 @@ void WriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer,
reinterpret_cast<uint64_t>(dst_gpu_addr), value); reinterpret_cast<uint64_t>(dst_gpu_addr), value);
} }
void WriteAtEndOfPipeClockCounterWithWriteBack(uint64_t submit_id, void WriteAtEndOfPipeClockCounterWithWriteBack(uint64_t submit_id, CommandBuffer* buffer,
CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) {
uint64_t* dst_gpu_addr,
uint64_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -150,7 +148,7 @@ void WriteAtEndOfPipeClockCounterWithWriteBack(uint64_t submit_id,
} }
void WriteAtEndOfPipeWithWriteBack64(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithWriteBack64(uint64_t submit_id, CommandBuffer* buffer,
uint64_t* dst_gpu_addr, uint64_t value) { uint64_t* dst_gpu_addr, uint64_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -162,7 +160,7 @@ void WriteAtEndOfPipeWithWriteBack64(uint64_t submit_id, CommandBuffer* buffer,
} }
void WriteAtEndOfPipeWithWriteBack32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithWriteBack32(uint64_t submit_id, CommandBuffer* buffer,
uint32_t* dst_gpu_addr, uint32_t value) { uint32_t* dst_gpu_addr, uint32_t value) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -172,10 +170,9 @@ void WriteAtEndOfPipeWithWriteBack32(uint64_t submit_id, CommandBuffer* buffer,
value, 0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr)); value, 0, 0, reinterpret_cast<uint64_t>(dst_gpu_addr));
} }
void WriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id, void WriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id, CommandBuffer* buffer,
CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value,
uint64_t* dst_gpu_addr, uint64_t value, uint32_t context_id) {
uint32_t context_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -197,10 +194,9 @@ void WriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id,
args); args);
} }
void WriteAtEndOfPipeWithInterruptWriteBack32(uint64_t submit_id, void WriteAtEndOfPipeWithInterruptWriteBack32(uint64_t submit_id, CommandBuffer* buffer,
CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value,
uint32_t* dst_gpu_addr, uint32_t value, uint32_t context_id) {
uint32_t context_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -221,8 +217,7 @@ void WriteAtEndOfPipeWithInterruptWriteBack32(uint64_t submit_id,
} }
void WriteAtEndOfPipeWithInterrupt64(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithInterrupt64(uint64_t submit_id, CommandBuffer* buffer,
uint64_t* dst_gpu_addr, uint64_t value, uint64_t* dst_gpu_addr, uint64_t value, uint32_t context_id) {
uint32_t context_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -245,8 +240,7 @@ void WriteAtEndOfPipeWithInterrupt64(uint64_t submit_id, CommandBuffer* buffer,
} }
void WriteAtEndOfPipeWithInterrupt32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithInterrupt32(uint64_t submit_id, CommandBuffer* buffer,
uint32_t* dst_gpu_addr, uint32_t value, uint32_t* dst_gpu_addr, uint32_t value, uint32_t context_id) {
uint32_t context_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -266,8 +260,8 @@ void WriteAtEndOfPipeWithInterrupt32(uint64_t submit_id, CommandBuffer* buffer,
args); args);
} }
uint64_t PrepareDisplayBufferFlip(CommandBuffer* buffer, int handle, int index, uint64_t PrepareDisplayBufferFlip(CommandBuffer* buffer, int handle, int index, int flip_mode,
int flip_mode, int64_t flip_arg) { int64_t flip_arg) {
for (;;) { for (;;) {
uint64_t request_id = 0; uint64_t request_id = 0;
const auto result = Presentation::DisplayBufferSubmitFlipFromGpu( const auto result = Presentation::DisplayBufferSubmitFlipFromGpu(
@@ -285,9 +279,10 @@ uint64_t PrepareDisplayBufferFlip(CommandBuffer* buffer, int handle, int index,
} }
} }
void WriteAtEndOfPipeWithInterruptWriteBackFlip32( void WriteAtEndOfPipeWithInterruptWriteBackFlip32(uint64_t submit_id, CommandBuffer* buffer,
uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, uint32_t* dst_gpu_addr, uint32_t value,
int index, int flip_mode, int64_t flip_arg, uint64_t request_id) { int handle, int index, int flip_mode,
int64_t flip_arg, uint64_t request_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -307,10 +302,9 @@ void WriteAtEndOfPipeWithInterruptWriteBackFlip32(
args); args);
} }
void WriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr,
uint32_t* dst_gpu_addr, uint32_t value, int handle, uint32_t value, int handle, int index, int flip_mode,
int index, int flip_mode, int64_t flip_arg, int64_t flip_arg, uint64_t request_id) {
uint64_t request_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(dst_gpu_addr == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
@@ -323,9 +317,8 @@ void WriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer,
SubmitLabel(buffer, CompleteDisplayBufferFlip, nullptr, args); SubmitLabel(buffer, CompleteDisplayBufferFlip, nullptr, args);
} }
void WriteAtEndOfPipeOnlyFlip(uint64_t submit_id, CommandBuffer* buffer, int handle, void WriteAtEndOfPipeOnlyFlip(uint64_t submit_id, CommandBuffer* buffer, int handle, int index,
int index, int flip_mode, int64_t flip_arg, int flip_mode, int64_t flip_arg, uint64_t request_id) {
uint64_t request_id) {
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
EXIT_IF(buffer == nullptr); EXIT_IF(buffer == nullptr);
EXIT_IF(buffer->IsInvalid()); EXIT_IF(buffer->IsInvalid());
+5 -5
View File
@@ -25,8 +25,8 @@ void WriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst
uint64_t value); uint64_t value);
void WriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, void WriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr,
uint32_t dw_offset, uint32_t dw_num); uint32_t dw_offset, uint32_t dw_num);
void WriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr,
uint64_t* dst_gpu_addr, uint64_t value); uint64_t value);
void WriteAtEndOfPipeClockCounterWithWriteBack(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeClockCounterWithWriteBack(uint64_t submit_id, CommandBuffer* buffer,
uint64_t* dst_gpu_addr, uint64_t value); uint64_t* dst_gpu_addr, uint64_t value);
void WriteAtEndOfPipeWithWriteBack32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithWriteBack32(uint64_t submit_id, CommandBuffer* buffer,
@@ -50,9 +50,9 @@ void WriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id, CommandBuffer*
int flip_mode, int64_t flip_arg); int flip_mode, int64_t flip_arg);
void WriteAtEndOfPipeOnlyFlip(uint64_t submit_id, CommandBuffer* buffer, int handle, int index, void WriteAtEndOfPipeOnlyFlip(uint64_t submit_id, CommandBuffer* buffer, int handle, int index,
int flip_mode, int64_t flip_arg, uint64_t request_id); int flip_mode, int64_t flip_arg, uint64_t request_id);
void WriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr,
uint32_t* dst_gpu_addr, uint32_t value, int handle, int index, uint32_t value, int handle, int index, int flip_mode,
int flip_mode, int64_t flip_arg, uint64_t request_id); int64_t flip_arg, uint64_t request_id);
void WriteAtEndOfPipeWithInterruptWriteBackFlip32(uint64_t submit_id, CommandBuffer* buffer, void WriteAtEndOfPipeWithInterruptWriteBackFlip32(uint64_t submit_id, CommandBuffer* buffer,
uint32_t* dst_gpu_addr, uint32_t value, uint32_t* dst_gpu_addr, uint32_t value,
int handle, int index, int flip_mode, int handle, int index, int flip_mode,
+130 -148
View File
@@ -21,8 +21,6 @@
#include "graphics/host_gpu/utils.h" #include "graphics/host_gpu/utils.h"
#include "kernel/memory.h" #include "kernel/memory.h"
#include <xxhash.h>
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cstdlib> #include <cstdlib>
@@ -30,6 +28,7 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <thread> #include <thread>
#include <xxhash.h>
namespace Libs::Graphics { namespace Libs::Graphics {
@@ -39,13 +38,13 @@ thread_local const void* g_texture_cache_lock_owner = nullptr;
thread_local const void* g_texture_fault_owner = nullptr; thread_local const void* g_texture_fault_owner = nullptr;
[[nodiscard]] uint64_t HashSampledImageEdges(const Image& image) { [[nodiscard]] uint64_t HashSampledImageEdges(const Image& image) {
constexpr uint64_t page_mask = TRACKER_PAGE_SIZE - 1; constexpr uint64_t page_mask = TRACKER_PAGE_SIZE - 1;
const uint64_t begin = image.address; const uint64_t begin = image.address;
const uint64_t end = image.address + image.size; const uint64_t end = image.address + image.size;
const uint64_t head_end = std::min(end, (begin + page_mask) & ~page_mask); const uint64_t head_end = std::min(end, (begin + page_mask) & ~page_mask);
const uint64_t tail_begin = std::max(begin, end & ~page_mask); const uint64_t tail_begin = std::max(begin, end & ~page_mask);
const uint64_t head_size = head_end - begin; const uint64_t head_size = head_end - begin;
const uint64_t tail_size = tail_begin < head_end ? end - head_end : end - tail_begin; const uint64_t tail_size = tail_begin < head_end ? end - head_end : end - tail_begin;
std::array<uint8_t, TRACKER_PAGE_SIZE * 2> bytes {}; std::array<uint8_t, TRACKER_PAGE_SIZE * 2> bytes {};
if (head_size + tail_size > bytes.size()) { if (head_size + tail_size > bytes.size()) {
EXIT("TextureCache: sampled-image edge hash range overflow\n"); EXIT("TextureCache: sampled-image edge hash range overflow\n");
@@ -243,10 +242,11 @@ void TextureCache::UnregisterImageLocked(CachedImage& image, bool release_tracki
image.registered = false; image.registered = false;
} }
VulkanImage* TextureCache::PublishImage(CommandBuffer* command, VulkanImage* TextureCache::PublishImage(CommandBuffer* command,
std::shared_ptr<CachedImage> image) { std::shared_ptr<CachedImage> image) {
if (command == nullptr || image == nullptr || image->image == nullptr || image->registered) { if (command == nullptr || image == nullptr || image->image == nullptr || image->registered) {
EXIT("TextureCache: invalid image publication, command=%p record=%p image=%p registered=%d\n", EXIT("TextureCache: invalid image publication, command=%p record=%p image=%p "
"registered=%d\n",
static_cast<const void*>(command), static_cast<const void*>(image.get()), static_cast<const void*>(command), static_cast<const void*>(image.get()),
image != nullptr ? static_cast<const void*>(image->image) : nullptr, image != nullptr ? static_cast<const void*>(image->image) : nullptr,
image != nullptr && image->registered); image != nullptr && image->registered);
@@ -389,7 +389,7 @@ struct TextureCache::ReadbackWorker {
} }
[[nodiscard]] ReadbackRange DownloadDepthTarget(CachedImage& cached, [[nodiscard]] ReadbackRange DownloadDepthTarget(CachedImage& cached,
bool require_fault_range = true) { bool require_fault_range = true) {
const auto& info = cached.depth; const auto& info = cached.depth;
const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0; const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0;
const bool has_htile = info.htile_address != 0 || info.htile_size != 0; const bool has_htile = info.htile_address != 0 || info.htile_size != 0;
@@ -423,8 +423,7 @@ struct TextureCache::ReadbackWorker {
(!has_htile || (expected_htile.size <= UINT64_MAX / info.layers && (!has_htile || (expected_htile.size <= UINT64_MAX / info.layers &&
info.htile_size == expected_htile.size * info.layers)); info.htile_size == expected_htile.size * info.layers));
if ((require_fault_range && !fault_in_depth) || has_stencil || info.address == 0 || if ((require_fault_range && !fault_in_depth) || has_stencil || info.address == 0 ||
info.size == 0 || info.size == 0 || info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
!prospero_layout || info.pitch != expected_pitch || !layered_sizes || !prospero_layout || info.pitch != expected_pitch || !layered_sizes ||
expected_depth.align != 65536u || cached.image->layers != info.layers || expected_depth.align != 65536u || cached.image->layers != info.layers ||
@@ -849,11 +848,11 @@ TextureCache::TextureCache(PageManager& page_manager, BufferCache& buffer_cache,
EXIT("TextureCache: construction is restricted to the main thread\n"); EXIT("TextureCache: construction is restricted to the main thread\n");
} }
m_dummy_textures = std::make_unique<DummyTextureCache>(); m_dummy_textures = std::make_unique<DummyTextureCache>();
m_readback = std::make_unique<ReadbackWorker>(*this); m_readback = std::make_unique<ReadbackWorker>(*this);
} }
TextureCache::CachedImage* TextureCache::FindGpuReadbackPageCandidateLocked(uint64_t vaddr, TextureCache::CachedImage* TextureCache::FindGpuReadbackPageCandidateLocked(uint64_t vaddr,
uint64_t size) { uint64_t size) {
CachedImage* selected = nullptr; CachedImage* selected = nullptr;
for (auto* cached: FindImagesInRegionLocked(vaddr, size, true)) { for (auto* cached: FindImagesInRegionLocked(vaddr, size, true)) {
if (!cached->IsGpuReadbackPageCandidate(vaddr, size)) { if (!cached->IsGpuReadbackPageCandidate(vaddr, size)) {
@@ -862,8 +861,7 @@ TextureCache::CachedImage* TextureCache::FindGpuReadbackPageCandidateLocked(uint
if (selected != nullptr) { if (selected != nullptr) {
EXIT("TextureCache: CPU fault has multiple GPU-modified image page candidates, " EXIT("TextureCache: CPU fault has multiple GPU-modified image page candidates, "
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 " first=%p second=%p\n", "addr=0x%016" PRIx64 " size=0x%016" PRIx64 " first=%p second=%p\n",
vaddr, size, static_cast<const void*>(selected), vaddr, size, static_cast<const void*>(selected), static_cast<const void*>(cached));
static_cast<const void*>(cached));
} }
selected = cached; selected = cached;
} }
@@ -929,8 +927,8 @@ void TextureCache::RetireSampledTargetAliases(GraphicContext* ctx, const ImageIn
const bool contained = const bool contained =
delta <= requested.size && cached->depth.size <= requested.size - delta; delta <= requested.size && cached->depth.size <= requested.size - delta;
const bool sampled_expansion = IsSampledDepthExpansion(requested, cached->depth); const bool sampled_expansion = IsSampledDepthExpansion(requested, cached->depth);
const bool exact_range = requested.address == cached->depth.address && const bool exact_range =
requested.size == cached->depth.size; requested.address == cached->depth.address && requested.size == cached->depth.size;
const bool supported = cached->ctx == ctx && !cached->buffer_modified && const bool supported = cached->ctx == ctx && !cached->buffer_modified &&
cached->depth.stencil_address == 0 && cached->depth.stencil_address == 0 &&
cached->depth.stencil_size == 0 && cached->depth.layers == 1 && cached->depth.stencil_size == 0 && cached->depth.layers == 1 &&
@@ -1049,8 +1047,7 @@ void TextureCache::ResolveStorageImageOverlaps(GraphicContext* ctx, const ImageI
RetireImages(retire); RetireImages(retire);
} }
void TextureCache::RetireStorageDepthAliasLocked(GraphicContext* ctx, void TextureCache::RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested) {
const ImageInfo& requested) {
CachedImage* selected = nullptr; CachedImage* selected = nullptr;
for (auto* entry: FindImagesInRegionLocked(requested.address, requested.size, true)) { for (auto* entry: FindImagesInRegionLocked(requested.address, requested.size, true)) {
auto& cached = *entry; auto& cached = *entry;
@@ -1059,7 +1056,7 @@ void TextureCache::RetireStorageDepthAliasLocked(GraphicContext* ctx,
continue; continue;
} }
const auto& depth = cached.depth; const auto& depth = cached.depth;
const bool exact_d32_uint = const bool exact_d32_uint =
cached.ctx == ctx && cached.gpu_modified && !cached.buffer_modified && cached.ctx == ctx && cached.gpu_modified && !cached.buffer_modified &&
depth.address == requested.address && depth.size == requested.size && depth.address == requested.address && depth.size == requested.size &&
depth.stencil_address == 0 && depth.stencil_size == 0 && depth.htile_address == 0 && depth.stencil_address == 0 && depth.stencil_size == 0 && depth.htile_address == 0 &&
@@ -1105,10 +1102,9 @@ TextureCache::~TextureCache() {
VulkanImage* TextureCache::FindTexture(CommandBuffer* command, GraphicContext* ctx, VulkanImage* TextureCache::FindTexture(CommandBuffer* command, GraphicContext* ctx,
const ImageInfo& info, bool metadata_read) { const ImageInfo& info, bool metadata_read) {
if (info.address == 0 || info.size == 0 || if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE ||
info.address >= TRACKER_ADDRESS_SIZE || info.size > TRACKER_ADDRESS_SIZE - info.address || info.size > TRACKER_ADDRESS_SIZE - info.address || info.width == 0 || info.height == 0 ||
info.width == 0 || info.height == 0 || info.depth == 0 || info.levels == 0 || info.depth == 0 || info.levels == 0 || info.levels >= 16 || info.view_levels == 0 ||
info.levels >= 16 || info.view_levels == 0 ||
info.base_level + info.view_levels > info.levels) { info.base_level + info.view_levels > info.levels) {
EXIT("TextureCache: invalid sampled-image request, command=%p ctx=%p addr=0x%016" PRIx64 EXIT("TextureCache: invalid sampled-image request, command=%p ctx=%p addr=0x%016" PRIx64
" size=0x%016" PRIx64 " extent=%ux%ux%u levels=%u\n", " size=0x%016" PRIx64 " extent=%ux%ux%u levels=%u\n",
@@ -1265,10 +1261,10 @@ VulkanImage* TextureCache::FindTexture(CommandBuffer* command, GraphicContext* c
} }
} }
m_images.reserve(m_images.size() + 1); m_images.reserve(m_images.size() + 1);
auto cached = std::make_shared<CachedImage>(); auto cached = std::make_shared<CachedImage>();
cached->kind = CachedImage::Kind::Texture; cached->kind = CachedImage::Kind::Texture;
cached->info = info; cached->info = info;
cached->ctx = ctx; cached->ctx = ctx;
VkComponentMapping components {}; VkComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, false, &cached->memory, &components); cached->image = ImageOps::CreateTexture(ctx, info, false, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
@@ -1292,11 +1288,10 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
const bool supported_depth_tile = const bool supported_depth_tile =
info.tile == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && info.tile == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) &&
IsSupportedStorageDepthTile(info.format, info.type, info.width, info.height, info.depth); IsSupportedStorageDepthTile(info.format, info.type, info.width, info.height, info.depth);
if (info.address == 0 || info.size == 0 || if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE ||
info.address >= TRACKER_ADDRESS_SIZE || info.size > TRACKER_ADDRESS_SIZE - info.address || info.size > TRACKER_ADDRESS_SIZE - info.address || info.width == 0 || info.height == 0 ||
info.width == 0 || info.height == 0 || info.depth == 0 || info.levels == 0 || info.depth == 0 || info.levels == 0 || info.levels > 16 || info.base_level >= info.levels ||
info.levels > 16 || info.base_level >= info.levels || info.view_levels != 1 || info.view_levels != 1 || info.base_array != 0 || !supported_type ||
info.base_array != 0 || !supported_type ||
(info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kLinear) && (info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kLinear) &&
info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) && info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
!supported_depth_tile) || !supported_depth_tile) ||
@@ -1354,7 +1349,7 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
if (match != nullptr) { if (match != nullptr) {
const bool cpu_modified = m_memory_tracker.IsRegionCpuModified(info.address, info.size); const bool cpu_modified = m_memory_tracker.IsRegionCpuModified(info.address, info.size);
const bool gpu_modified = m_memory_tracker.IsRegionGpuModified(info.address, info.size); const bool gpu_modified = m_memory_tracker.IsRegionGpuModified(info.address, info.size);
const auto rebind = ClassifyStorageBufferRebind( const auto rebind = ClassifyStorageBufferRebind(
buffer_overlap, match->gpu_modified, match->buffer_modified, gpu_modified, cpu_modified, buffer_overlap, match->gpu_modified, match->buffer_modified, gpu_modified, cpu_modified,
IsCoherentGuestImageSource(source, info.address, info.size)); IsCoherentGuestImageSource(source, info.address, info.size));
if (rebind == StorageBufferRebind::Unsupported) { if (rebind == StorageBufferRebind::Unsupported) {
@@ -1373,9 +1368,9 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, true, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, true, [](uint64_t, uint64_t) noexcept {},
[&]() noexcept { [&]() noexcept {
m_tiler.DetileImage( m_tiler.DetileImage(match->ctx,
match->ctx, static_cast<GpuTextureVulkanImage*>(match->image), match->info, static_cast<GpuTextureVulkanImage*>(match->image),
source, true, true); match->info, source, true, true);
}); });
match->buffer_modified = false; match->buffer_modified = false;
match->gpu_modified = true; match->gpu_modified = true;
@@ -1402,10 +1397,10 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
ResolveStorageImageOverlaps(ctx, info); ResolveStorageImageOverlaps(ctx, info);
m_images.reserve(m_images.size() + 1); m_images.reserve(m_images.size() + 1);
auto cached = std::make_shared<CachedImage>(); auto cached = std::make_shared<CachedImage>();
cached->kind = CachedImage::Kind::StorageTexture; cached->kind = CachedImage::Kind::StorageTexture;
cached->info = info; cached->info = info;
cached->ctx = ctx; cached->ctx = ctx;
VkComponentMapping components {}; VkComponentMapping components {};
cached->image = ImageOps::CreateTexture(ctx, info, true, &cached->memory, &components); cached->image = ImageOps::CreateTexture(ctx, info, true, &cached->memory, &components);
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
@@ -1415,8 +1410,8 @@ StorageTextureVulkanImage* TextureCache::FindStorageTexture(CommandBuffer* com
cached->info, source, false, true); cached->info, source, false, true);
}); });
cached->gpu_modified = true; cached->gpu_modified = true;
ImageOps::CreateTextureViews(ctx, static_cast<GpuTextureVulkanImage*>(cached->image), info, true, ImageOps::CreateTextureViews(ctx, static_cast<GpuTextureVulkanImage*>(cached->image), info,
components); true, components);
return static_cast<StorageTextureVulkanImage*>(PublishImage(command, std::move(cached))); return static_cast<StorageTextureVulkanImage*>(PublishImage(command, std::move(cached)));
} }
@@ -1424,11 +1419,11 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
GraphicContext* ctx, GraphicContext* ctx,
const RenderTargetInfo& info) { const RenderTargetInfo& info) {
const bool standard64 = IsSupportedStandard64RenderTarget(info); const bool standard64 = IsSupportedStandard64RenderTarget(info);
if (info.address == 0 || info.size == 0 || if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE ||
info.address >= TRACKER_ADDRESS_SIZE || info.size > TRACKER_ADDRESS_SIZE - info.address || info.size > TRACKER_ADDRESS_SIZE - info.address || info.format == VK_FORMAT_UNDEFINED ||
info.format == VK_FORMAT_UNDEFINED || info.width == 0 || info.height == 0 || info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.pitch < info.width || info.bytes_per_element == 0 || info.levels == 0 || info.bytes_per_element == 0 || info.levels == 0 || info.levels > 16 || info.layers == 0 ||
info.levels > 16 || info.layers == 0 || info.size % info.layers != 0 || info.size % info.layers != 0 ||
(info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kLinear) && (info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kLinear) &&
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) && info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
!standard64)) { !standard64)) {
@@ -1579,9 +1574,10 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
} }
break; break;
case RenderTargetOverlap::RetireTarget: case RenderTargetOverlap::RetireTarget:
supported = cached.kind == CachedImage::Kind::RenderTarget || supported =
(cached.kind == CachedImage::Kind::DepthTarget && target_buffer_overlap && cached.kind == CachedImage::Kind::RenderTarget ||
IsCoherentGuestImageSource(target_source, info.address, info.size)); (cached.kind == CachedImage::Kind::DepthTarget && target_buffer_overlap &&
IsCoherentGuestImageSource(target_source, info.address, info.size));
if (supported && cached.kind == CachedImage::Kind::DepthTarget) { if (supported && cached.kind == CachedImage::Kind::DepthTarget) {
buffer_owned_depth_retire.push_back(&cached); buffer_owned_depth_retire.push_back(&cached);
} }
@@ -1632,8 +1628,8 @@ RenderTextureVulkanImage* TextureCache::FindRenderTarget(CommandBuffer*
tail_address, tail_size, true, [](uint64_t, uint64_t) noexcept {}, tail_address, tail_size, true, [](uint64_t, uint64_t) noexcept {},
[&]() noexcept { [&]() noexcept {
ImageOps::UploadRenderTargetLayers( ImageOps::UploadRenderTargetLayers(
ctx, static_cast<RenderTextureVulkanImage*>(cached->image), info, old.layers, ctx, static_cast<RenderTextureVulkanImage*>(cached->image), info,
info.layers - old.layers, false); old.layers, info.layers - old.layers, false);
}); });
} }
std::vector<ImageImageCopy> regions; std::vector<ImageImageCopy> regions;
@@ -1658,11 +1654,10 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
const DepthTargetInfo& info) { const DepthTargetInfo& info) {
const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0; const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0;
const bool has_htile = info.htile_address != 0 || info.htile_size != 0; const bool has_htile = info.htile_address != 0 || info.htile_size != 0;
if (info.address == 0 || info.size == 0 || if (info.address == 0 || info.size == 0 || info.address >= TRACKER_ADDRESS_SIZE ||
info.address >= TRACKER_ADDRESS_SIZE || info.size > TRACKER_ADDRESS_SIZE - info.address || info.size > TRACKER_ADDRESS_SIZE - info.address || (info.address & 0xffffu) != 0 ||
(info.address & 0xffffu) != 0 || info.width == 0 || info.height == 0 || info.width == 0 || info.height == 0 || info.pitch < info.width || info.layers == 0 ||
info.pitch < info.width || info.layers == 0 || info.size % info.layers != 0 || info.size % info.layers != 0 || info.size > UINT32_MAX || info.stencil_size > UINT32_MAX ||
info.size > UINT32_MAX || info.stencil_size > UINT32_MAX ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
(has_stencil && (has_stencil &&
(info.stencil_address == 0 || info.stencil_size == 0 || (info.stencil_address == 0 || info.stencil_size == 0 ||
@@ -1760,9 +1755,8 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, true, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, true, [](uint64_t, uint64_t) noexcept {},
[&]() noexcept { [&]() noexcept {
m_tiler.DetileImage(ctx, m_tiler.DetileImage(ctx, static_cast<DepthStencilVulkanImage*>(match->image),
static_cast<DepthStencilVulkanImage*>(match->image), info, info, depth_source, true);
depth_source, true);
}); });
match->buffer_modified = false; match->buffer_modified = false;
match->gpu_modified = true; match->gpu_modified = true;
@@ -1832,17 +1826,15 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
case DepthOverlap::RetireStorage: case DepthOverlap::RetireStorage:
supported = cached.kind == CachedImage::Kind::StorageTexture && supported = cached.kind == CachedImage::Kind::StorageTexture &&
cached.gpu_modified && !cached.buffer_modified && cached.gpu_modified && !cached.buffer_modified &&
!cached.info.IsCpuDirty() && !cached.info.IsCpuDirty() && retired_storage_source == nullptr &&
retired_storage_source == nullptr && native_depth_source == nullptr && native_depth_source == nullptr && discarded_depth_source == nullptr;
discarded_depth_source == nullptr;
if (supported) { if (supported) {
retired_storage_source = entry; retired_storage_source = entry;
} }
break; break;
case DepthOverlap::ExpandTarget: case DepthOverlap::ExpandTarget:
supported = supported = cached.kind == CachedImage::Kind::DepthTarget &&
cached.kind == CachedImage::Kind::DepthTarget && native_depth_source == nullptr && native_depth_source == nullptr && retired_storage_source == nullptr;
retired_storage_source == nullptr;
if (supported) { if (supported) {
native_depth_source = entry; native_depth_source = entry;
} }
@@ -1872,11 +1864,10 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
retired_storage_source->info.size); retired_storage_source->info.size);
retired_storage_source->gpu_modified = false; retired_storage_source->gpu_modified = false;
} }
const auto* transition_source = native_depth_source != nullptr const auto* transition_source =
? native_depth_source.get() native_depth_source != nullptr
: (discarded_depth_source != nullptr ? native_depth_source.get()
? discarded_depth_source.get() : (discarded_depth_source != nullptr ? discarded_depth_source.get() : nullptr);
: nullptr);
RetireImages(retire, transition_source); RetireImages(retire, transition_source);
const bool coherent_guest_stencil = const bool coherent_guest_stencil =
has_stencil && has_stencil &&
@@ -2050,8 +2041,8 @@ TextureCache::RegisterVideoOutSurfaces(GraphicContext* ctx,
m_memory_tracker.ForEachUploadRange( m_memory_tracker.ForEachUploadRange(
info.address, info.size, false, [](uint64_t, uint64_t) noexcept {}, info.address, info.size, false, [](uint64_t, uint64_t) noexcept {},
[&]() noexcept { [&]() noexcept {
ImageOps::UploadVideoOut( ImageOps::UploadVideoOut(ctx, static_cast<VideoOutVulkanImage*>(cached->image),
ctx, static_cast<VideoOutVulkanImage*>(cached->image), info, false); info, false);
}); });
} else { } else {
// A compressed guest surface cannot be decoded without its DCC metadata. Establish the // A compressed guest surface cannot be decoded without its DCC metadata. Establish the
@@ -2180,8 +2171,8 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
static_cast<const void*>(command), vaddr, size); static_cast<const void*>(command), vaddr, size);
} }
m_buffer_cache.ValidateGpuAccess(vaddr, size, false, true); m_buffer_cache.ValidateGpuAccess(vaddr, size, false, true);
std::lock_guard transaction(m_resource_mutex); std::lock_guard transaction(m_resource_mutex);
FaultSafeTextureLock lock(this, m_lock); FaultSafeTextureLock lock(this, m_lock);
enum class ClearAspect : uint8_t { None, Color, Depth, Stencil }; enum class ClearAspect : uint8_t { None, Color, Depth, Stencil };
auto classify = [vaddr, size](const CachedImage& cached) { auto classify = [vaddr, size](const CachedImage& cached) {
const bool color = cached.kind == CachedImage::Kind::VideoOut || const bool color = cached.kind == CachedImage::Kind::VideoOut ||
@@ -2238,8 +2229,7 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
return false; return false;
} }
uint8_t stencil_clear = 0; uint8_t stencil_clear = 0;
if (aspect == ClearAspect::Stencil && if (aspect == ClearAspect::Stencil && !DecodePackedStencilClear(packed_clear, &stencil_clear)) {
!DecodePackedStencilClear(packed_clear, &stencil_clear)) {
return false; return false;
} }
@@ -2257,8 +2247,7 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
!buffer_overlap || IsCoherentGuestImageSource(source, vaddr, size); !buffer_overlap || IsCoherentGuestImageSource(source, vaddr, size);
const bool image_cpu_modified = m_memory_tracker.IsRegionCpuModified(vaddr, size); const bool image_cpu_modified = m_memory_tracker.IsRegionCpuModified(vaddr, size);
const bool invalid_common = !buffer_source_valid || buffer_cpu_modified || const bool invalid_common = !buffer_source_valid || buffer_cpu_modified ||
buffer_gpu_modified || match->buffer_modified || buffer_gpu_modified || match->buffer_modified || image_cpu_modified;
image_cpu_modified;
if (aspect == ClearAspect::Color && invalid_common) { if (aspect == ClearAspect::Color && invalid_common) {
EXIT("TextureCache: compute image clear requires exclusive GPU image ownership, " EXIT("TextureCache: compute image clear requires exclusive GPU image ownership, "
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "addr=0x%016" PRIx64 " size=0x%016" PRIx64
@@ -2276,8 +2265,8 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
" gpu_modified=%d buffer_overlap=%d source_valid=%d buffer_cpu_modified=%d" " gpu_modified=%d buffer_overlap=%d source_valid=%d buffer_cpu_modified=%d"
" buffer_gpu_modified=%d buffer_modified=%d image_cpu_modified=%d\n", " buffer_gpu_modified=%d buffer_modified=%d image_cpu_modified=%d\n",
plane, source_name, vaddr, size, match->gpu_modified, buffer_overlap, plane, source_name, vaddr, size, match->gpu_modified, buffer_overlap,
buffer_source_valid, buffer_cpu_modified, buffer_gpu_modified, buffer_source_valid, buffer_cpu_modified, buffer_gpu_modified, match->buffer_modified,
match->buffer_modified, image_cpu_modified); image_cpu_modified);
} }
auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()]; auto* vk_buffer = command->GetPool()->buffers[command->GetIndex()];
@@ -2288,9 +2277,8 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
} }
GraphicsRenderColorImageBarrier(vk_buffer, match->image, GraphicsRenderColorImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const VkImageSubresourceRange range {VK_IMAGE_ASPECT_COLOR_BIT, 0, const VkImageSubresourceRange range {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS,
VK_REMAINING_MIP_LEVELS, 0, 0, match->image->layers};
match->image->layers};
vkCmdClearColorImage(vk_buffer, match->image->image, match->image->layout, &clear, 1, vkCmdClearColorImage(vk_buffer, match->image->image, match->image->layout, &clear, 1,
&range); &range);
GraphicsRenderColorImageBarrier(vk_buffer, match->image, RENDER_COLOR_IMAGE_LAYOUT); GraphicsRenderColorImageBarrier(vk_buffer, match->image, RENDER_COLOR_IMAGE_LAYOUT);
@@ -2312,7 +2300,7 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer* command, uint64_t vaddr,
GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image, GraphicsRenderDepthStencilImageBarrier(vk_buffer, match->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const VkClearDepthStencilValue clear {depth_clear, stencil_clear}; const VkClearDepthStencilValue clear {depth_clear, stencil_clear};
const auto clear_aspect = static_cast<VkImageAspectFlags>( const auto clear_aspect = static_cast<VkImageAspectFlags>(
aspect == ClearAspect::Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT); aspect == ClearAspect::Depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT);
const VkImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0, const VkImageSubresourceRange range {clear_aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
match->image->layers}; match->image->layers};
@@ -2441,9 +2429,8 @@ void TextureCache::PrepareHostWrite(uint64_t vaddr, uint64_t size) {
MarkSampledAliasesCpuDirtyLocked(vaddr, size); MarkSampledAliasesCpuDirtyLocked(vaddr, size);
} }
void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached, void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached, uint64_t write_address,
uint64_t write_address, uint64_t write_size) {
uint64_t write_size) {
const bool render_target = cached.kind == CachedImage::Kind::RenderTarget; const bool render_target = cached.kind == CachedImage::Kind::RenderTarget;
const bool video_out = cached.kind == CachedImage::Kind::VideoOut; const bool video_out = cached.kind == CachedImage::Kind::VideoOut;
const bool storage = cached.kind == CachedImage::Kind::StorageTexture; const bool storage = cached.kind == CachedImage::Kind::StorageTexture;
@@ -2485,18 +2472,17 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached,
const bool layered_size = const bool layered_size =
single_slice && static_cast<uint64_t>(exact.size) * target.layers == target.size; single_slice && static_cast<uint64_t>(exact.size) * target.layers == target.size;
if (storage && target.levels > 1) { if (storage && target.levels > 1) {
single_slice = TileGetRenderTargetMipLayout( single_slice = TileGetRenderTargetMipLayout(target.width, target.height, target.pitch,
target.width, target.height, target.pitch, target.bytes_per_element, target.levels, target.bytes_per_element, target.levels, &exact,
&exact, nullptr, nullptr); nullptr, nullptr);
} }
const bool exact_tiled = const bool exact_tiled = tiled && exact.align == 65536 &&
tiled && exact.align == 65536 && (storage ? single_slice && exact.size == target.size : layered_size);
(storage ? single_slice && exact.size == target.size : layered_size); const bool valid_kind =
const bool valid_kind = render_target || storage || (video_out && cached.video_out.compression == render_target || storage ||
VideoOutCompression::Uncompressed); (video_out && cached.video_out.compression == VideoOutCompression::Uncompressed);
if (!valid_kind || !cached.gpu_modified || cached.buffer_modified || if (!valid_kind || !cached.gpu_modified || cached.buffer_modified ||
(!storage && target.levels != 1) || (!storage && target.levels != 1) || target.size > UINT32_MAX || (!linear && !exact_tiled) ||
target.size > UINT32_MAX || (!linear && !exact_tiled) ||
HasMetaOverlapLocked(target.address, target.size)) { HasMetaOverlapLocked(target.address, target.size)) {
EXIT("TextureCache: unsupported color-image buffer synchronization, " EXIT("TextureCache: unsupported color-image buffer synchronization, "
"addr=0x%016" PRIx64 " size=0x%016" PRIx64 "addr=0x%016" PRIx64 " size=0x%016" PRIx64
@@ -2512,8 +2498,7 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached,
write_address - target.address > target.size || write_address - target.address > target.size ||
write_size > target.size - (write_address - target.address)) { write_size > target.size - (write_address - target.address)) {
EXIT("TextureCache: image synchronization write is outside backing, " EXIT("TextureCache: image synchronization write is outside backing, "
"write=0x%016" PRIx64 "+0x%016" PRIx64 " image=0x%016" PRIx64 "write=0x%016" PRIx64 "+0x%016" PRIx64 " image=0x%016" PRIx64 "+0x%016" PRIx64 "\n",
"+0x%016" PRIx64 "\n",
write_address, write_size, target.address, target.size); write_address, write_size, target.address, target.size);
} }
const auto slice_size = target.size / target.layers; const auto slice_size = target.size / target.layers;
@@ -2550,7 +2535,7 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached,
} }
} else { } else {
regions = MakeLayeredImageBufferCopies(target.layers, slice_size, target.pitch, regions = MakeLayeredImageBufferCopies(target.layers, slice_size, target.pitch,
target.width, target.height); target.width, target.height);
} }
UtilFillBuffer(cached.ctx, m_buffer_transition_linear.data(), target.size, regions, UtilFillBuffer(cached.ctx, m_buffer_transition_linear.data(), target.size, regions,
cached.image, cached.image->layout); cached.image, cached.image->layout);
@@ -2580,39 +2565,40 @@ void TextureCache::SynchronizeColorImageToBufferLocked(CachedImage& cached,
cached.buffer_modified = true; cached.buffer_modified = true;
} }
void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint64_t write_address,
uint64_t write_address, uint64_t write_size) {
uint64_t write_size) { const auto& info = cached.depth;
const auto& info = cached.depth; const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0;
const bool has_stencil = info.stencil_address != 0 || info.stencil_size != 0; const bool has_htile = info.htile_address != 0 || info.htile_size != 0;
const bool has_htile = info.htile_address != 0 || info.htile_size != 0;
TileSizeAlign expected_stencil {}; TileSizeAlign expected_stencil {};
TileSizeAlign expected_htile {}; TileSizeAlign expected_htile {};
TileSizeAlign expected_depth {}; TileSizeAlign expected_depth {};
const bool d16 = info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) && const bool d16 =
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2; info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
const bool d32 = info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) && info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2;
info.format == VK_FORMAT_D32_SFLOAT && info.bytes_per_element == 4; const bool d32 =
const bool layout = (d16 || d32) && info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
TileGetDepthSize(info.width, info.height, 0, info.format == VK_FORMAT_D32_SFLOAT && info.bytes_per_element == 4;
Prospero::GpuEnumValue(d16 ? Prospero::DepthFormat::kZ16 const bool layout =
: Prospero::DepthFormat::kZ32F), (d16 || d32) &&
Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid), TileGetDepthSize(info.width, info.height, 0,
false, &expected_stencil, &expected_htile, Prospero::GpuEnumValue(d16 ? Prospero::DepthFormat::kZ16
&expected_depth); : Prospero::DepthFormat::kZ32F),
Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid), false,
&expected_stencil, &expected_htile, &expected_depth);
if (cached.kind != CachedImage::Kind::DepthTarget || !cached.gpu_modified || if (cached.kind != CachedImage::Kind::DepthTarget || !cached.gpu_modified ||
cached.buffer_modified || write_address != info.address || write_size != info.size || cached.buffer_modified || write_address != info.address || write_size != info.size ||
has_stencil || has_htile || info.layers != 1 || !layout || has_stencil || has_htile || info.layers != 1 || !layout || expected_depth.align != 65536 ||
expected_depth.align != 65536 || expected_depth.size != info.size || expected_depth.size != info.size || cached.image->format != info.format ||
cached.image->format != info.format || cached.image->extent.width != info.width || cached.image->extent.width != info.width || cached.image->extent.height != info.height ||
cached.image->extent.height != info.height || HasMetaOverlapLocked(info.address, info.size)) { HasMetaOverlapLocked(info.address, info.size)) {
EXIT("TextureCache: unsupported depth-image buffer synchronization, " EXIT("TextureCache: unsupported depth-image buffer synchronization, "
"write=0x%016" PRIx64 "+0x%016" PRIx64 " depth=0x%016" PRIx64 "write=0x%016" PRIx64 "+0x%016" PRIx64 " depth=0x%016" PRIx64 "+0x%016" PRIx64
"+0x%016" PRIx64 " extent=%ux%u layers=%u format=%d guest=%u bpe=%u" " extent=%ux%u layers=%u format=%d guest=%u bpe=%u"
" stencil=%d htile=%d gpu_modified=%d buffer_modified=%d\n", " stencil=%d htile=%d gpu_modified=%d buffer_modified=%d\n",
write_address, write_size, info.address, info.size, info.width, info.height, info.layers, write_address, write_size, info.address, info.size, info.width, info.height,
static_cast<int>(info.format), info.guest_format, info.bytes_per_element, has_stencil, info.layers, static_cast<int>(info.format), info.guest_format, info.bytes_per_element,
has_htile, cached.gpu_modified, cached.buffer_modified); has_stencil, has_htile, cached.gpu_modified, cached.buffer_modified);
} }
VulkanDeviceWaitIdle(cached.ctx); VulkanDeviceWaitIdle(cached.ctx);
m_buffer_transition_linear.resize(info.size); m_buffer_transition_linear.resize(info.size);
@@ -2623,7 +2609,8 @@ void TextureCache::SynchronizeDepthImageToBufferLocked(CachedImage& cached,
cached.image->layout); cached.image->layout);
m_buffer_transition_guest.resize(info.size); m_buffer_transition_guest.resize(info.size);
m_tiler.TileImage(m_buffer_transition_guest.data(), m_buffer_transition_linear.data(), info); m_tiler.TileImage(m_buffer_transition_guest.data(), m_buffer_transition_linear.data(), info);
Libs::LibKernel::Memory::WriteBacking(info.address, m_buffer_transition_guest.data(), info.size); Libs::LibKernel::Memory::WriteBacking(info.address, m_buffer_transition_guest.data(),
info.size);
m_memory_tracker.ForEachDownloadRange<true>(info.address, info.size, m_memory_tracker.ForEachDownloadRange<true>(info.address, info.size,
[](uint64_t, uint64_t) noexcept {}); [](uint64_t, uint64_t) noexcept {});
m_buffer_cache.PublishImageBacking(write_address, write_size); m_buffer_cache.PublishImageBacking(write_address, write_size);
@@ -2687,9 +2674,7 @@ bool TextureCache::InvalidateMemoryFromGPU(uint64_t vaddr, uint64_t size,
case BufferImageWrite::InvalidateVideoOut: case BufferImageWrite::InvalidateVideoOut:
case BufferImageWrite::InvalidateStorageTexture: case BufferImageWrite::InvalidateStorageTexture:
case BufferImageWrite::InvalidateDepthTarget: case BufferImageWrite::InvalidateDepthTarget:
case BufferImageWrite::InvalidateRenderTarget: case BufferImageWrite::InvalidateRenderTarget: cached.buffer_modified = true; return true;
cached.buffer_modified = true;
return true;
case BufferImageWrite::SynchronizeRenderTarget: case BufferImageWrite::SynchronizeRenderTarget:
case BufferImageWrite::SynchronizeStorageTexture: case BufferImageWrite::SynchronizeStorageTexture:
SynchronizeColorImageToBufferLocked(cached, vaddr, size); SynchronizeColorImageToBufferLocked(cached, vaddr, size);
@@ -2709,8 +2694,8 @@ bool TextureCache::InvalidateMemoryFromGPU(uint64_t vaddr, uint64_t size,
} }
DepthStencilVulkanImage* TextureCache::FindDepthTargetByRange(CommandBuffer* command, DepthStencilVulkanImage* TextureCache::FindDepthTargetByRange(CommandBuffer* command,
uint64_t vaddr, uint64_t size, uint64_t vaddr, uint64_t size,
bool allow_containing_sampled) { bool allow_containing_sampled) {
if (command == nullptr || vaddr == 0 || size == 0 || vaddr >= TRACKER_ADDRESS_SIZE || if (command == nullptr || vaddr == 0 || size == 0 || vaddr >= TRACKER_ADDRESS_SIZE ||
size > TRACKER_ADDRESS_SIZE - vaddr) { size > TRACKER_ADDRESS_SIZE - vaddr) {
EXIT("TextureCache: invalid depth-target range query, addr=0x%016" PRIx64 EXIT("TextureCache: invalid depth-target range query, addr=0x%016" PRIx64
@@ -2724,9 +2709,8 @@ DepthStencilVulkanImage* TextureCache::FindDepthTargetByRange(CommandBuffer* com
!cached->OverlapsRange(vaddr, size, false)) { !cached->OverlapsRange(vaddr, size, false)) {
continue; continue;
} }
const bool containing_sampled = allow_containing_sampled && const bool containing_sampled =
vaddr == cached->depth.address && allow_containing_sampled && vaddr == cached->depth.address && size > cached->depth.size;
size > cached->depth.size;
if ((!IsDepthTargetRangeCompatible(cached->depth, vaddr, size) && !containing_sampled) || if ((!IsDepthTargetRangeCompatible(cached->depth, vaddr, size) && !containing_sampled) ||
found != nullptr) { found != nullptr) {
EXIT("TextureCache: incompatible or ambiguous depth-target range, addr=0x%016" PRIx64 EXIT("TextureCache: incompatible or ambiguous depth-target range, addr=0x%016" PRIx64
@@ -2766,8 +2750,8 @@ RenderTextureVulkanImage* TextureCache::FindRenderTargetByRange(CommandBuffer* c
" size=0x%016" PRIx64 "\n", " size=0x%016" PRIx64 "\n",
vaddr, size); vaddr, size);
} }
FaultSafeTextureLock lock(this, m_lock); FaultSafeTextureLock lock(this, m_lock);
CachedImage* found = nullptr; CachedImage* found = nullptr;
for (auto* cached: FindImagesInRegionLocked(vaddr, size, false)) { for (auto* cached: FindImagesInRegionLocked(vaddr, size, false)) {
if (cached->kind != CachedImage::Kind::RenderTarget || if (cached->kind != CachedImage::Kind::RenderTarget ||
!ImageRangeOverlaps(vaddr, size, cached->Address(), cached->Size())) { !ImageRangeOverlaps(vaddr, size, cached->Address(), cached->Size())) {
@@ -2784,8 +2768,7 @@ RenderTextureVulkanImage* TextureCache::FindRenderTargetByRange(CommandBuffer* c
if (found != nullptr) { if (found != nullptr) {
EXIT("TextureCache: incompatible or ambiguous render-target range, addr=0x%016" PRIx64 EXIT("TextureCache: incompatible or ambiguous render-target range, addr=0x%016" PRIx64
" size=0x%016" PRIx64 " cached=0x%016" PRIx64 "+0x%016" PRIx64 " previous=%p\n", " size=0x%016" PRIx64 " cached=0x%016" PRIx64 "+0x%016" PRIx64 " previous=%p\n",
vaddr, size, cached->Address(), cached->Size(), vaddr, size, cached->Address(), cached->Size(), static_cast<const void*>(found));
static_cast<const void*>(found));
} }
found = cached; found = cached;
} }
@@ -2804,14 +2787,13 @@ RenderTextureVulkanImage* TextureCache::FindRenderTargetByRange(CommandBuffer* c
TextureCache::RegionInfo TextureCache::QueryRegion(uint64_t vaddr, uint64_t size) { TextureCache::RegionInfo TextureCache::QueryRegion(uint64_t vaddr, uint64_t size) {
if (vaddr == 0 || size == 0 || vaddr >= TRACKER_ADDRESS_SIZE || if (vaddr == 0 || size == 0 || vaddr >= TRACKER_ADDRESS_SIZE ||
size > TRACKER_ADDRESS_SIZE - vaddr) { size > TRACKER_ADDRESS_SIZE - vaddr) {
EXIT("TextureCache: invalid region query, addr=0x%016" PRIx64 EXIT("TextureCache: invalid region query, addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
" size=0x%016" PRIx64 "\n",
vaddr, size); vaddr, size);
} }
FaultSafeTextureLock lock(this, m_lock); FaultSafeTextureLock lock(this, m_lock);
RegionInfo result; RegionInfo result;
const auto candidates = FindImagesInRegionLocked(vaddr, size, true); const auto candidates = FindImagesInRegionLocked(vaddr, size, true);
result.image_pages = !candidates.empty(); result.image_pages = !candidates.empty();
for (const auto* cached: candidates) { for (const auto* cached: candidates) {
const bool bytes = cached->OverlapsRange(vaddr, size, false); const bool bytes = cached->OverlapsRange(vaddr, size, false);
result.image_bytes |= bytes; result.image_bytes |= bytes;
+21 -21
View File
@@ -34,13 +34,13 @@ class ResourceMutex;
class TextureCache { class TextureCache {
public: public:
struct RegionInfo { struct RegionInfo {
bool image_pages = false; bool image_pages = false;
bool image_bytes = false; bool image_bytes = false;
bool gpu_image_bytes = false; bool gpu_image_bytes = false;
bool non_sampled_pages = false; bool non_sampled_pages = false;
bool metadata_pages = false; bool metadata_pages = false;
bool metadata_bytes = false; bool metadata_bytes = false;
bool gpu_metadata_bytes = false; bool gpu_metadata_bytes = false;
}; };
TextureCache(PageManager& page_manager, BufferCache& buffer_cache, TextureCache(PageManager& page_manager, BufferCache& buffer_cache,
@@ -103,15 +103,15 @@ public:
FindDepthTargetByRange(CommandBuffer* command, uint64_t vaddr, uint64_t size, FindDepthTargetByRange(CommandBuffer* command, uint64_t vaddr, uint64_t size,
bool allow_containing_sampled = false); bool allow_containing_sampled = false);
[[nodiscard]] RegionInfo QueryRegion(uint64_t vaddr, uint64_t size); [[nodiscard]] RegionInfo QueryRegion(uint64_t vaddr, uint64_t size);
void RegisterMeta(uint64_t vaddr, uint64_t size, uint32_t layers = 1); void RegisterMeta(uint64_t vaddr, uint64_t size, uint32_t layers = 1);
[[nodiscard]] bool IsMeta(uint64_t vaddr); [[nodiscard]] bool IsMeta(uint64_t vaddr);
[[nodiscard]] bool IsMetaRange(uint64_t vaddr, uint64_t size); [[nodiscard]] bool IsMetaRange(uint64_t vaddr, uint64_t size);
[[nodiscard]] bool IsMetaCleared(uint64_t vaddr, uint32_t slice); [[nodiscard]] bool IsMetaCleared(uint64_t vaddr, uint32_t slice);
[[nodiscard]] bool ClearMeta(uint64_t vaddr); [[nodiscard]] bool ClearMeta(uint64_t vaddr);
[[nodiscard]] bool TouchMeta(uint64_t vaddr, uint32_t slice, bool is_clear); [[nodiscard]] bool TouchMeta(uint64_t vaddr, uint32_t slice, bool is_clear);
[[nodiscard]] bool InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint64_t size, [[nodiscard]] bool InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint64_t size,
PageFaultPhase phase) noexcept; PageFaultPhase phase) noexcept;
void UnmapMemory(uint64_t vaddr, uint64_t size); void UnmapMemory(uint64_t vaddr, uint64_t size);
VulkanImage* GetDummySampledTexture(bool uint_format, bool image_3d); VulkanImage* GetDummySampledTexture(bool uint_format, bool image_3d);
VulkanImage* GetDummyStorageTexture(bool uint_format, bool image_3d); VulkanImage* GetDummyStorageTexture(bool uint_format, bool image_3d);
@@ -137,10 +137,10 @@ private:
void RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested); void RetireStorageDepthAliasLocked(GraphicContext* ctx, const ImageInfo& requested);
void RegisterImageLocked(CachedImage& image); void RegisterImageLocked(CachedImage& image);
void UnregisterImageLocked(CachedImage& image, bool release_tracking); void UnregisterImageLocked(CachedImage& image, bool release_tracking);
[[nodiscard]] VulkanImage* PublishImage(CommandBuffer* command, [[nodiscard]] VulkanImage* PublishImage(CommandBuffer* command,
std::shared_ptr<CachedImage> image); std::shared_ptr<CachedImage> image);
[[nodiscard]] std::vector<CachedImage*> [[nodiscard]] std::vector<CachedImage*> FindImagesInRegionLocked(uint64_t vaddr, uint64_t size,
FindImagesInRegionLocked(uint64_t vaddr, uint64_t size, bool page_overlap); bool page_overlap);
void RequireRetirementIsolation(const std::vector<CachedImage*>& retire, const char* operation, void RequireRetirementIsolation(const std::vector<CachedImage*>& retire, const char* operation,
uint64_t address, uint64_t size) const; uint64_t address, uint64_t size) const;
void RetireImages(const std::vector<CachedImage*>& retire, void RetireImages(const std::vector<CachedImage*>& retire,
@@ -150,7 +150,7 @@ private:
void SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint64_t write_address, void SynchronizeDepthImageToBufferLocked(CachedImage& cached, uint64_t write_address,
uint64_t write_size); uint64_t write_size);
std::unique_ptr<DummyTextureCache> m_dummy_textures; std::unique_ptr<DummyTextureCache> m_dummy_textures;
TrackingSpinLock m_lock; TrackingSpinLock m_lock;
std::mutex m_fault_mutex; std::mutex m_fault_mutex;
MemoryTracker m_memory_tracker; MemoryTracker m_memory_tracker;
+12 -12
View File
@@ -163,7 +163,7 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer; auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
if (standard64) { if (standard64) {
TileConvertLinearToTiledStandard64KB32(guest_slice, linear_slice, info.width, TileConvertLinearToTiledStandard64KB32(guest_slice, linear_slice, info.width,
info.height, info.pitch, slice_size); info.height, info.pitch, slice_size);
} else { } else {
TileConvertLinearToTiledRenderTarget(guest_slice, linear_slice, info.width, info.height, TileConvertLinearToTiledRenderTarget(guest_slice, linear_slice, info.width, info.height,
info.pitch, info.bytes_per_element, slice_size); info.pitch, info.bytes_per_element, slice_size);
@@ -172,30 +172,30 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
} }
void Tiler::TileImage(void* dst, const void* src, const ImageInfo& info) const { void Tiler::TileImage(void* dst, const void* src, const ImageInfo& info) const {
const bool image_2d = info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && const bool image_2d =
info.depth == 1; info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && info.depth == 1;
const auto bytes_per_element = Prospero::RenderTargetBytesPerElement(info.format); const auto bytes_per_element = Prospero::RenderTargetBytesPerElement(info.format);
if (!image_2d || info.levels == 0 || info.levels > 16 || if (!image_2d || info.levels == 0 || info.levels > 16 ||
info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) || info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
bytes_per_element == 0) { bytes_per_element == 0) {
EXIT("Tiler: unsupported storage-texture tile, addr=0x%016" PRIx64 EXIT("Tiler: unsupported storage-texture tile, addr=0x%016" PRIx64 "+0x%016" PRIx64
"+0x%016" PRIx64 " extent=%ux%ux%u levels=%u tile=%u format=%u\n", " extent=%ux%ux%u levels=%u tile=%u format=%u\n",
info.address, info.size, info.width, info.height, info.depth, info.levels, info.tile, info.address, info.size, info.width, info.height, info.depth, info.levels, info.tile,
info.format); info.format);
} }
auto layout = TextureCalcUploadLayout(info.format, info.width, info.height, info.levels, auto layout = TextureCalcUploadLayout(info.format, info.width, info.height, info.levels,
info.depth, info.pitch, info.tile, info.size, true, false, info.depth, info.pitch, info.tile, info.size, true, false,
false, "StorageTextureReadback"); false, "StorageTextureReadback");
auto regions = TextureBuildUploadRegions( auto regions = TextureBuildUploadRegions(layout, Prospero::SurfaceFormat(info.format),
layout, Prospero::SurfaceFormat(info.format), info.width, info.height, info.depth, info.width, info.height, info.depth, info.levels,
info.levels, false, false, TextureUploadDestination::MipLevels, false, false, TextureUploadDestination::MipLevels,
TextureUploadSliceLayout::MipChainPerSlice); TextureUploadSliceLayout::MipChainPerSlice);
std::memset(dst, 0, info.size); std::memset(dst, 0, info.size);
for (uint32_t level = 0; level < info.levels; level++) { for (uint32_t level = 0; level < info.levels; level++) {
const auto& level_size = layout.level_sizes[level]; const auto& level_size = layout.level_sizes[level];
const auto guest_offset = level_size.src_size != 0 ? level_size.src_offset const auto guest_offset =
: level_size.offset; level_size.src_size != 0 ? level_size.src_offset : level_size.offset;
auto* guest = static_cast<uint8_t*>(dst) + guest_offset; auto* guest = static_cast<uint8_t*>(dst) + guest_offset;
const auto* linear = static_cast<const uint8_t*>(src) + regions[level].offset; const auto* linear = static_cast<const uint8_t*>(src) + regions[level].offset;
TileConvertLinearToTiledRenderTarget( TileConvertLinearToTiledRenderTarget(
guest, linear, regions[level].width, regions[level].height, regions[level].pitch, guest, linear, regions[level].width, regions[level].height, regions[level].pitch,
+1 -2
View File
@@ -92,8 +92,7 @@ void UtilCopyImageWithBuffer(CommandBuffer* buffer, GraphicContext* ctx, VulkanI
uint64_t dst_layout); uint64_t dst_layout);
void UtilBlitPreparedImage(CommandBuffer* buffer, VulkanImage* src_image, void UtilBlitPreparedImage(CommandBuffer* buffer, VulkanImage* src_image,
VulkanSwapchain* dst_swapchain); VulkanSwapchain* dst_swapchain);
void UtilClearColorImage(CommandBuffer* buffer, VulkanImage* image, void UtilClearColorImage(CommandBuffer* buffer, VulkanImage* image, const VkClearColorValue& color);
const VkClearColorValue& color);
void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size,
uint32_t src_pitch, uint64_t dst_layout); uint32_t src_pitch, uint64_t dst_layout);
void UtilFillImage(GraphicContext* ctx, DepthStencilVulkanImage* dst_image, const void* src_data, void UtilFillImage(GraphicContext* ctx, DepthStencilVulkanImage* dst_image, const void* src_data,
+4 -4
View File
@@ -18,11 +18,11 @@ struct DisplayBufferImage {
}; };
DisplayBufferImage DisplayBufferFind(uint64_t addr, bool render_target = false); DisplayBufferImage DisplayBufferFind(uint64_t addr, bool render_target = false);
int DisplayBufferSubmitFlipFromGpu(Graphics::CommandBuffer* buffer, int handle, int index, int DisplayBufferSubmitFlipFromGpu(Graphics::CommandBuffer* buffer, int handle, int index,
int flip_mode, int64_t flip_arg, uint64_t* request_id); int flip_mode, int64_t flip_arg, uint64_t* request_id);
uint64_t DisplayBufferPrepareNextFlipOnGpu(Graphics::CommandBuffer* buffer); uint64_t DisplayBufferPrepareNextFlipOnGpu(Graphics::CommandBuffer* buffer);
void DisplayBufferCompleteFlipFromGpu(uint64_t request_id); void DisplayBufferCompleteFlipFromGpu(uint64_t request_id);
void DisplayBufferWaitForFlipQueueSlot(); void DisplayBufferWaitForFlipQueueSlot();
} // namespace Libs::Presentation } // namespace Libs::Presentation
+17 -17
View File
@@ -163,28 +163,28 @@ public:
virtual ~FlipQueue() { KYTY_NOT_IMPLEMENTED; } virtual ~FlipQueue() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(FlipQueue); KYTY_CLASS_NO_COPY(FlipQueue);
bool Reserve(VideoOutConfig* cfg, int index, int64_t flip_arg, bool gpu_eop, bool Reserve(VideoOutConfig* cfg, int index, int64_t flip_arg, bool gpu_eop,
uint64_t* request_id); uint64_t* request_id);
void Prepare(uint64_t request_id, Graphics::CommandBuffer* buffer); void Prepare(uint64_t request_id, Graphics::CommandBuffer* buffer);
uint64_t PrepareNextCpu(Graphics::CommandBuffer* buffer); uint64_t PrepareNextCpu(Graphics::CommandBuffer* buffer);
void Complete(uint64_t request_id); void Complete(uint64_t request_id);
void WaitForSubmitSlot(); void WaitForSubmitSlot();
bool Flip(uint32_t micros); bool Flip(uint32_t micros);
bool HasPending(VideoOutConfig* cfg, int start_index, int count); bool HasPending(VideoOutConfig* cfg, int start_index, int count);
void GetFlipStatus(VideoOutConfig* cfg, VideoOutFlipStatus* out); void GetFlipStatus(VideoOutConfig* cfg, VideoOutFlipStatus* out);
void Wait(VideoOutConfig* cfg, int index); void Wait(VideoOutConfig* cfg, int index);
private: private:
enum class RequestState { Reserved, Recording, Ready, Presenting }; enum class RequestState { Reserved, Recording, Ready, Presenting };
struct Request { struct Request {
uint64_t id; uint64_t id;
VideoOutConfig* cfg; VideoOutConfig* cfg;
int index; int index;
int64_t flip_arg; int64_t flip_arg;
uint64_t submit_ptc; uint64_t submit_ptc;
bool gpu_eop; bool gpu_eop;
RequestState state; RequestState state;
Graphics::PreparedFrame* frame; Graphics::PreparedFrame* frame;
}; };
@@ -194,7 +194,7 @@ private:
Common::CondVar m_done_cond_var; Common::CondVar m_done_cond_var;
std::list<Request> m_requests; std::list<Request> m_requests;
std::list<Request> m_cpu_requests; std::list<Request> m_cpu_requests;
bool m_processing = false; bool m_processing = false;
uint64_t m_next_request_id = 1; uint64_t m_next_request_id = 1;
}; };
+3 -3
View File
@@ -17,9 +17,9 @@ VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
GraphicContext* WindowGetGraphicContext(); GraphicContext* WindowGetGraphicContext();
void WindowInit(uint32_t width, uint32_t height); void WindowInit(uint32_t width, uint32_t height);
void WindowRun(); void WindowRun();
void WindowWaitForGraphicInitialized(); void WindowWaitForGraphicInitialized();
PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* image); PreparedFrame* WindowPrepareFrame(CommandBuffer* buffer, VideoOutVulkanImage* image);
PreparedFrame* WindowPrepareBlankFrame(CommandBuffer* buffer, uint32_t width, uint32_t height, PreparedFrame* WindowPrepareBlankFrame(CommandBuffer* buffer, uint32_t width, uint32_t height,
bool opaque); bool opaque);
@@ -59,9 +59,9 @@
namespace Libs::Graphics { namespace Libs::Graphics {
struct PreparedFrame { struct PreparedFrame {
VulkanImage image {VulkanImageType::Unknown}; VulkanImage image {VulkanImageType::Unknown};
std::unique_ptr<CommandBuffer> present_commands; std::unique_ptr<CommandBuffer> present_commands;
bool busy = false; bool busy = false;
}; };
class PreparedFramePool { class PreparedFramePool {
@@ -385,7 +385,8 @@ static void VulkanRecreateSwapchain() {
} }
static void ValidatePreparedCommand(CommandBuffer* buffer) { static void ValidatePreparedCommand(CommandBuffer* buffer) {
if (buffer == nullptr || buffer->IsInvalid() || buffer->GetQueue() != GraphicContext::QUEUE_GFX) { if (buffer == nullptr || buffer->IsInvalid() ||
buffer->GetQueue() != GraphicContext::QUEUE_GFX) {
EXIT("prepared frames must be recorded on the graphics queue\n"); EXIT("prepared frames must be recorded on the graphics queue\n");
} }
EXIT_IF(g_render_ctx == nullptr); EXIT_IF(g_render_ctx == nullptr);
@@ -18,16 +18,17 @@ enum class ComponentType {
struct BufferFormatInfo { struct BufferFormatInfo {
Prospero::BufferFormat format = Prospero::BufferFormat::kInvalid; Prospero::BufferFormat format = Prospero::BufferFormat::kInvalid;
ComponentType type = ComponentType::Unknown; ComponentType type = ComponentType::Unknown;
uint32_t component_count = 0; uint32_t component_count = 0;
uint32_t byte_size = 0; uint32_t byte_size = 0;
uint32_t component_bits[4] = {}; uint32_t component_bits[4] = {};
uint32_t component_bit_offset[4] = {}; uint32_t component_bit_offset[4] = {};
bool packed_bitfield = false; bool packed_bitfield = false;
}; };
constexpr Prospero::BufferFormat DecodeTBufferFormat(uint32_t data_format, uint32_t number_format) { constexpr Prospero::BufferFormat DecodeTBufferFormat(uint32_t data_format, uint32_t number_format) {
return static_cast<Prospero::BufferFormat>(((number_format & 0x7u) << 4u) | (data_format & 0xfu)); return static_cast<Prospero::BufferFormat>(((number_format & 0x7u) << 4u) |
(data_format & 0xfu));
} }
constexpr ComponentType GetFormatComponentType(Prospero::BufferFormat format) { constexpr ComponentType GetFormatComponentType(Prospero::BufferFormat format) {
@@ -1,8 +1,8 @@
#include "graphics/shader/recompiler/ShaderIR.h" #include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include "common/assert.h" #include "common/assert.h"
#include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include <algorithm> #include <algorithm>
#include <fmt/format.h> #include <fmt/format.h>
@@ -403,7 +403,6 @@ Decoder::Operand M0Operand() {
return operand; return operand;
} }
namespace { namespace {
bool LowerScalarSelect(const Decoder::Instruction& decoded, BasicBlock* block, std::string* error) { bool LowerScalarSelect(const Decoder::Instruction& decoded, BasicBlock* block, std::string* error) {
@@ -1145,7 +1144,6 @@ bool LowerDecodedInstruction(const Decoder::Instruction& inst, BasicBlock* block
return LowerImplemented(inst, block, error); return LowerImplemented(inst, block, error);
} }
bool LowerImplemented(const Decoder::Instruction& decoded, BasicBlock* block, std::string* error) { bool LowerImplemented(const Decoder::Instruction& decoded, BasicBlock* block, std::string* error) {
Instruction inst; Instruction inst;
inst.pc = decoded.pc; inst.pc = decoded.pc;
@@ -14,36 +14,34 @@ bool IsVectorCarryOutOpcode(Decoder::Opcode opcode);
bool ScalarResultWritesSccNonZero(Decoder::Opcode opcode); bool ScalarResultWritesSccNonZero(Decoder::Opcode opcode);
bool ScalarResultIs64Bit(Decoder::Opcode opcode); bool ScalarResultIs64Bit(Decoder::Opcode opcode);
Operand MakeSccOperand(); Operand MakeSccOperand();
Operand MakeImmediateU32(uint32_t value); Operand MakeImmediateU32(uint32_t value);
Operand MakePcRelativeU32(uint32_t value); Operand MakePcRelativeU32(uint32_t value);
bool AppendScalarResultSccNonZero(const Decoder::Instruction& decoded, BasicBlock* block, bool AppendScalarResultSccNonZero(const Decoder::Instruction& decoded, BasicBlock* block,
std::string* error); std::string* error);
uint32_t VectorByteConvertIndex(Decoder::Opcode opcode); uint32_t VectorByteConvertIndex(Decoder::Opcode opcode);
void CopyOperandModifiers(const Decoder::Operand& decoded, Operand& operand); void CopyOperandModifiers(const Decoder::Operand& decoded, Operand& operand);
bool LowerRegisterOperand(const Decoder::Operand& decoded, Operand* operand, bool LowerRegisterOperand(const Decoder::Operand& decoded, Operand* operand, std::string* error);
std::string* error); bool LowerSourceOperand(const Decoder::Operand& decoded, Operand* operand, std::string* error);
bool LowerSourceOperand(const Decoder::Operand& decoded, Operand* operand, std::string* error); void ApplyDppDestinationMask(const Decoder::Instruction& decoded, Operand& dst);
void ApplyDppDestinationMask(const Decoder::Instruction& decoded, Operand& dst); uint32_t ResourceIndexFromOperand(const Decoder::Operand& operand);
uint32_t ResourceIndexFromOperand(const Decoder::Operand& operand); MemoryInfo MemoryInfoFromDecoded(const Decoder::Instruction& decoded, ResourceKind kind);
MemoryInfo MemoryInfoFromDecoded(const Decoder::Instruction& decoded, ResourceKind kind); uint32_t RawScalarLoadBase(const Decoder::Operand& operand);
uint32_t RawScalarLoadBase(const Decoder::Operand& operand); void ClearRegisterOffsetModifiers(Decoder::Operand& operand);
void ClearRegisterOffsetModifiers(Decoder::Operand& operand); bool TryGetScalarDestinationCode(const Decoder::Operand& operand, uint32_t& code);
bool TryGetScalarDestinationCode(const Decoder::Operand& operand, uint32_t& code); bool TryOffsetScalarDestination(const Decoder::Operand& operand, uint32_t index,
bool TryOffsetScalarDestination(const Decoder::Operand& operand, uint32_t index, Decoder::Operand* result);
Decoder::Operand* result);
Decoder::Operand OffsetDecodedRegister(const Decoder::Operand& operand, uint32_t index); Decoder::Operand OffsetDecodedRegister(const Decoder::Operand& operand, uint32_t index);
MemoryInfo OffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind, MemoryInfo OffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind,
uint32_t dword_index); uint32_t dword_index);
uint32_t TypedBufferComponentOffsetBytes(const Decoder::Instruction& decoded, uint32_t TypedBufferComponentOffsetBytes(const Decoder::Instruction& decoded,
uint32_t component_index); uint32_t component_index);
uint32_t TypedBufferFormatComponentCount(const Decoder::Instruction& decoded); uint32_t TypedBufferFormatComponentCount(const Decoder::Instruction& decoded);
bool LowerMoveImmediateU32(uint32_t pc, const Decoder::Operand& dst, uint32_t value, bool LowerMoveImmediateU32(uint32_t pc, const Decoder::Operand& dst, uint32_t value,
BasicBlock* block, std::string* error); BasicBlock* block, std::string* error);
MemoryInfo OffsetBufferMemoryInfo(const Decoder::Instruction& decoded, MemoryInfo OffsetBufferMemoryInfo(const Decoder::Instruction& decoded, uint32_t component_index);
uint32_t component_index); MemoryInfo ByteOffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind,
MemoryInfo ByteOffsetMemoryInfo(const Decoder::Instruction& decoded, ResourceKind kind, uint32_t byte_offset);
uint32_t byte_offset);
ResourceKind FlatSegmentResourceKind(uint32_t segment); ResourceKind FlatSegmentResourceKind(uint32_t segment);
const Decoder::Operand& DecodedSourceAt(const Decoder::Instruction& decoded, uint32_t index); const Decoder::Operand& DecodedSourceAt(const Decoder::Instruction& decoded, uint32_t index);
Decoder::Operand M0Operand(); Decoder::Operand M0Operand();
@@ -1,8 +1,7 @@
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include "common/assert.h" #include "common/assert.h"
#include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include <algorithm> #include <algorithm>
#include <fmt/format.h> #include <fmt/format.h>
@@ -1,8 +1,7 @@
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include "common/assert.h" #include "common/assert.h"
#include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include <algorithm> #include <algorithm>
#include <fmt/format.h> #include <fmt/format.h>
@@ -470,7 +469,6 @@ bool LowerImageOperation(const Decoder::Instruction& decoded, BasicBlock* block,
return true; return true;
} }
} // namespace } // namespace
bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock* block, bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock* block,
@@ -647,7 +645,6 @@ bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock* blo
} }
} }
bool IsMemoryOpcode(Decoder::Opcode opcode) { bool IsMemoryOpcode(Decoder::Opcode opcode) {
switch (opcode) { switch (opcode) {
case Decoder::Opcode::SLoadDword: case Decoder::Opcode::SLoadDword:
@@ -1,8 +1,7 @@
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include "common/assert.h" #include "common/assert.h"
#include "graphics/shader/recompiler/BufferFormat.h" #include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/ShaderIR.h"
#include "graphics/shader/recompiler/shaderIR/ShaderIRInternal.h"
#include <algorithm> #include <algorithm>
#include <fmt/format.h> #include <fmt/format.h>
@@ -425,7 +424,6 @@ constexpr LowerMap LOWER_OPS[] = {
{Decoder::Opcode::ImageGather4H, Opcode::ImageGather4}, {Decoder::Opcode::ImageGather4H, Opcode::ImageGather4},
}; };
} // namespace } // namespace
void SetError(std::string* error, const char* message) { void SetError(std::string* error, const char* message) {
@@ -913,9 +913,11 @@ uint32_t AddressSourceCount(const IR::Instruction& inst, uint32_t first_src);
bool IsFormattedBufferComponent(const IR::Instruction& inst); bool IsFormattedBufferComponent(const IR::Instruction& inst);
Prospero::BufferFormat FormattedBufferFormat(const EmitterState& state, const IR::Instruction& inst); Prospero::BufferFormat FormattedBufferFormat(const EmitterState& state,
const IR::Instruction& inst);
IR::Instruction WithFormatComponentByteOffset(const IR::Instruction& inst, Prospero::BufferFormat format); IR::Instruction WithFormatComponentByteOffset(const IR::Instruction& inst,
Prospero::BufferFormat format);
uint32_t EmitTBufferBitcastF32ToU32(EmitterState* state, uint32_t value); uint32_t EmitTBufferBitcastF32ToU32(EmitterState* state, uint32_t value);
@@ -953,7 +955,7 @@ bool EmitTypedTBufferLoad(EmitterState* state, const IR::Instruction& inst,
bool EmitFormattedBufferLoad(EmitterState* state, const IR::Instruction& inst); bool EmitFormattedBufferLoad(EmitterState* state, const IR::Instruction& inst);
uint32_t FormattedBufferDwordStoreComponentCount(Prospero::BufferFormat format, uint32_t FormattedBufferDwordStoreComponentCount(Prospero::BufferFormat format,
uint32_t opcode_components); uint32_t opcode_components);
bool EmitBufferIntegerFormatStore(EmitterState* state, const IR::Instruction& inst); bool EmitBufferIntegerFormatStore(EmitterState* state, const IR::Instruction& inst);
@@ -726,13 +726,16 @@ bool IsFormattedBufferComponent(const IR::Instruction& inst) {
inst.memory.data_dwords == 1u; inst.memory.data_dwords == 1u;
} }
Prospero::BufferFormat FormattedBufferFormat(const EmitterState& state, const IR::Instruction& inst) { Prospero::BufferFormat FormattedBufferFormat(const EmitterState& state,
const IR::Instruction& inst) {
return inst.memory.typed return inst.memory.typed
? Format::DecodeTBufferFormat(inst.memory.data_format, inst.memory.number_format) ? Format::DecodeTBufferFormat(inst.memory.data_format, inst.memory.number_format)
: static_cast<Prospero::BufferFormat>(StorageBufferFormat(state, inst.memory, inst.pc)); : static_cast<Prospero::BufferFormat>(
StorageBufferFormat(state, inst.memory, inst.pc));
} }
IR::Instruction WithFormatComponentByteOffset(const IR::Instruction& inst, Prospero::BufferFormat format) { IR::Instruction WithFormatComponentByteOffset(const IR::Instruction& inst,
Prospero::BufferFormat format) {
auto rebased = inst; auto rebased = inst;
if (inst.memory.typed || inst.memory.component_index == 0u) { if (inst.memory.typed || inst.memory.component_index == 0u) {
return rebased; return rebased;
@@ -972,7 +975,7 @@ bool EmitFormattedBufferLoad(EmitterState* state, const IR::Instruction& inst) {
} }
uint32_t FormattedBufferDwordStoreComponentCount(Prospero::BufferFormat format, uint32_t FormattedBufferDwordStoreComponentCount(Prospero::BufferFormat format,
uint32_t opcode_components) { uint32_t opcode_components) {
switch (format) { switch (format) {
case Prospero::BufferFormat::k32UInt: case Prospero::BufferFormat::k32UInt:
case Prospero::BufferFormat::k32SInt: case Prospero::BufferFormat::k32SInt:
+27 -17
View File
@@ -9,9 +9,9 @@
#include "common/magicEnum.h" #include "common/magicEnum.h"
#include "common/profiler.h" #include "common/profiler.h"
#include "common/stringUtils.h" #include "common/stringUtils.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/graphicsRun.h" #include "graphics/guest_gpu/graphicsRun.h"
#include "graphics/guest_gpu/hardwareContext.h" #include "graphics/guest_gpu/hardwareContext.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/shader/recompiler/ShaderDecoder.h" #include "graphics/shader/recompiler/ShaderDecoder.h"
#include "graphics/shader/recompiler/ShaderRecompiler.h" #include "graphics/shader/recompiler/ShaderRecompiler.h"
#include "graphics/shader/shaderVertexMetadata.h" #include "graphics/shader/shaderVertexMetadata.h"
@@ -562,14 +562,18 @@ static uint32_t VertexAttribFormatToBufferFormat(uint32_t format) {
{Prospero::VertexAttribFormat::k10_11_11Float, Prospero::BufferFormat::k10_11_11Float}, {Prospero::VertexAttribFormat::k10_11_11Float, Prospero::BufferFormat::k10_11_11Float},
{Prospero::VertexAttribFormat::k2_10_10_10UNorm, Prospero::BufferFormat::k2_10_10_10UNorm}, {Prospero::VertexAttribFormat::k2_10_10_10UNorm, Prospero::BufferFormat::k2_10_10_10UNorm},
{Prospero::VertexAttribFormat::k2_10_10_10SNorm, Prospero::BufferFormat::k2_10_10_10SNorm}, {Prospero::VertexAttribFormat::k2_10_10_10SNorm, Prospero::BufferFormat::k2_10_10_10SNorm},
{Prospero::VertexAttribFormat::k2_10_10_10UScaled, Prospero::BufferFormat::k2_10_10_10UScaled}, {Prospero::VertexAttribFormat::k2_10_10_10UScaled,
{Prospero::VertexAttribFormat::k2_10_10_10SScaled, Prospero::BufferFormat::k2_10_10_10SScaled}, Prospero::BufferFormat::k2_10_10_10UScaled},
{Prospero::VertexAttribFormat::k2_10_10_10SScaled,
Prospero::BufferFormat::k2_10_10_10SScaled},
{Prospero::VertexAttribFormat::k2_10_10_10UInt, Prospero::BufferFormat::k2_10_10_10UInt}, {Prospero::VertexAttribFormat::k2_10_10_10UInt, Prospero::BufferFormat::k2_10_10_10UInt},
{Prospero::VertexAttribFormat::k2_10_10_10SInt, Prospero::BufferFormat::k2_10_10_10SInt}, {Prospero::VertexAttribFormat::k2_10_10_10SInt, Prospero::BufferFormat::k2_10_10_10SInt},
{Prospero::VertexAttribFormat::k10_10_10_2UNorm, Prospero::BufferFormat::k10_10_10_2UNorm}, {Prospero::VertexAttribFormat::k10_10_10_2UNorm, Prospero::BufferFormat::k10_10_10_2UNorm},
{Prospero::VertexAttribFormat::k10_10_10_2SNorm, Prospero::BufferFormat::k10_10_10_2SNorm}, {Prospero::VertexAttribFormat::k10_10_10_2SNorm, Prospero::BufferFormat::k10_10_10_2SNorm},
{Prospero::VertexAttribFormat::k10_10_10_2UScaled, Prospero::BufferFormat::k10_10_10_2UScaled}, {Prospero::VertexAttribFormat::k10_10_10_2UScaled,
{Prospero::VertexAttribFormat::k10_10_10_2SScaled, Prospero::BufferFormat::k10_10_10_2SScaled}, Prospero::BufferFormat::k10_10_10_2UScaled},
{Prospero::VertexAttribFormat::k10_10_10_2SScaled,
Prospero::BufferFormat::k10_10_10_2SScaled},
{Prospero::VertexAttribFormat::k10_10_10_2UInt, Prospero::BufferFormat::k10_10_10_2UInt}, {Prospero::VertexAttribFormat::k10_10_10_2UInt, Prospero::BufferFormat::k10_10_10_2UInt},
{Prospero::VertexAttribFormat::k10_10_10_2SInt, Prospero::BufferFormat::k10_10_10_2SInt}, {Prospero::VertexAttribFormat::k10_10_10_2SInt, Prospero::BufferFormat::k10_10_10_2SInt},
{Prospero::VertexAttribFormat::k8_8_8_8UNorm, Prospero::BufferFormat::k8_8_8_8UNorm}, {Prospero::VertexAttribFormat::k8_8_8_8UNorm, Prospero::BufferFormat::k8_8_8_8UNorm},
@@ -581,19 +585,25 @@ static uint32_t VertexAttribFormatToBufferFormat(uint32_t format) {
{Prospero::VertexAttribFormat::k32_32UInt, Prospero::BufferFormat::k32_32UInt}, {Prospero::VertexAttribFormat::k32_32UInt, Prospero::BufferFormat::k32_32UInt},
{Prospero::VertexAttribFormat::k32_32SInt, Prospero::BufferFormat::k32_32SInt}, {Prospero::VertexAttribFormat::k32_32SInt, Prospero::BufferFormat::k32_32SInt},
{Prospero::VertexAttribFormat::k32_32Float, Prospero::BufferFormat::k32_32Float}, {Prospero::VertexAttribFormat::k32_32Float, Prospero::BufferFormat::k32_32Float},
{Prospero::VertexAttribFormat::k16_16_16_16UNorm, Prospero::BufferFormat::k16_16_16_16UNorm}, {Prospero::VertexAttribFormat::k16_16_16_16UNorm,
{Prospero::VertexAttribFormat::k16_16_16_16SNorm, Prospero::BufferFormat::k16_16_16_16SNorm}, Prospero::BufferFormat::k16_16_16_16UNorm},
{Prospero::VertexAttribFormat::k16_16_16_16UScaled, Prospero::BufferFormat::k16_16_16_16UScaled}, {Prospero::VertexAttribFormat::k16_16_16_16SNorm,
{Prospero::VertexAttribFormat::k16_16_16_16SScaled, Prospero::BufferFormat::k16_16_16_16SScaled}, Prospero::BufferFormat::k16_16_16_16SNorm},
{Prospero::VertexAttribFormat::k16_16_16_16UScaled,
Prospero::BufferFormat::k16_16_16_16UScaled},
{Prospero::VertexAttribFormat::k16_16_16_16SScaled,
Prospero::BufferFormat::k16_16_16_16SScaled},
{Prospero::VertexAttribFormat::k16_16_16_16UInt, Prospero::BufferFormat::k16_16_16_16UInt}, {Prospero::VertexAttribFormat::k16_16_16_16UInt, Prospero::BufferFormat::k16_16_16_16UInt},
{Prospero::VertexAttribFormat::k16_16_16_16SInt, Prospero::BufferFormat::k16_16_16_16SInt}, {Prospero::VertexAttribFormat::k16_16_16_16SInt, Prospero::BufferFormat::k16_16_16_16SInt},
{Prospero::VertexAttribFormat::k16_16_16_16Float, Prospero::BufferFormat::k16_16_16_16Float}, {Prospero::VertexAttribFormat::k16_16_16_16Float,
Prospero::BufferFormat::k16_16_16_16Float},
{Prospero::VertexAttribFormat::k32_32_32UInt, Prospero::BufferFormat::k32_32_32UInt}, {Prospero::VertexAttribFormat::k32_32_32UInt, Prospero::BufferFormat::k32_32_32UInt},
{Prospero::VertexAttribFormat::k32_32_32SInt, Prospero::BufferFormat::k32_32_32SInt}, {Prospero::VertexAttribFormat::k32_32_32SInt, Prospero::BufferFormat::k32_32_32SInt},
{Prospero::VertexAttribFormat::k32_32_32Float, Prospero::BufferFormat::k32_32_32Float}, {Prospero::VertexAttribFormat::k32_32_32Float, Prospero::BufferFormat::k32_32_32Float},
{Prospero::VertexAttribFormat::k32_32_32_32UInt, Prospero::BufferFormat::k32_32_32_32UInt}, {Prospero::VertexAttribFormat::k32_32_32_32UInt, Prospero::BufferFormat::k32_32_32_32UInt},
{Prospero::VertexAttribFormat::k32_32_32_32SInt, Prospero::BufferFormat::k32_32_32_32SInt}, {Prospero::VertexAttribFormat::k32_32_32_32SInt, Prospero::BufferFormat::k32_32_32_32SInt},
{Prospero::VertexAttribFormat::k32_32_32_32Float, Prospero::BufferFormat::k32_32_32_32Float}, {Prospero::VertexAttribFormat::k32_32_32_32Float,
Prospero::BufferFormat::k32_32_32_32Float},
}; };
for (const auto& entry: format_map) { for (const auto& entry: format_map) {
@@ -793,9 +803,9 @@ static bool ShaderGetStaticInputInfoVS(const HW::VertexShaderInfo* regs,
static void ShaderGetStaticInputInfoPS( static void ShaderGetStaticInputInfoPS(
const HW::PixelShaderInfo* regs, const HW::ShaderRegisters* sh, const HW::PixelShaderInfo* regs, const HW::ShaderRegisters* sh,
const ShaderVertexInputInfo* vs_info, const ShaderVertexInputInfo* vs_info,
std::span<const Prospero::ColorComponentMapping, 8> target_export_mapping, std::span<const Prospero::ColorComponentMapping, 8> target_export_mapping,
ShaderPixelInputInfo* ps_info) { ShaderPixelInputInfo* ps_info) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
EXIT_IF(vs_info == nullptr); EXIT_IF(vs_info == nullptr);
@@ -834,10 +844,10 @@ static void ShaderGetStaticInputInfoPS(
: 0; : 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
ps_info->target_output_mode[i] = sh->target_output_mode[i]; ps_info->target_output_mode[i] = sh->target_output_mode[i];
ps_info->target_export_mapping[i] = ps_info->target_export_mapping[i] = sh->target_output_mode[i] != 0
sh->target_output_mode[i] != 0 ? target_export_mapping[i] ? target_export_mapping[i]
: Prospero::ColorComponentMapping {}; : Prospero::ColorComponentMapping {};
} }
ps_info->mrt_output_mask = 0; ps_info->mrt_output_mask = 0;
} }
+20 -20
View File
@@ -96,26 +96,26 @@ struct ShaderComputeInputInfo {
}; };
struct ShaderPixelInputInfo { struct ShaderPixelInputInfo {
uint32_t interpolator_settings[32] = {0}; uint32_t interpolator_settings[32] = {0};
uint32_t input_num = 0; uint32_t input_num = 0;
uint32_t ps_system_input_base = 0; uint32_t ps_system_input_base = 0;
uint8_t target_output_mode[8] = {}; uint8_t target_output_mode[8] = {};
std::array<Prospero::ColorComponentMapping, 8> target_export_mapping = {}; std::array<Prospero::ColorComponentMapping, 8> target_export_mapping = {};
uint32_t mrt_output_mask = 0; uint32_t mrt_output_mask = 0;
uint32_t descriptor_set = 0; uint32_t descriptor_set = 0;
bool ps_pos_x = false; bool ps_pos_x = false;
bool ps_pos_y = false; bool ps_pos_y = false;
bool ps_pos_xy = false; bool ps_pos_xy = false;
bool ps_pos_z = false; bool ps_pos_z = false;
bool ps_pos_w = false; bool ps_pos_w = false;
bool ps_front_face = false; bool ps_front_face = false;
bool ps_no_perspective = false; bool ps_no_perspective = false;
bool ps_pixel_kill_enable = false; bool ps_pixel_kill_enable = false;
bool ps_depth_export_enable = false; bool ps_depth_export_enable = false;
bool ps_sample_mask_export_enable = false; bool ps_sample_mask_export_enable = false;
bool ps_early_z = false; bool ps_early_z = false;
bool ps_execute_on_noop = false; bool ps_execute_on_noop = false;
ShaderStageRuntime stage; ShaderStageRuntime stage;
bool HasPositionInput() const { return ps_pos_x || ps_pos_y || ps_pos_z || ps_pos_w; } bool HasPositionInput() const { return ps_pos_x || ps_pos_y || ps_pos_z || ps_pos_w; }
}; };
+2 -2
View File
@@ -39,10 +39,10 @@
#include <QUrl> #include <QUrl>
#include <QtCore> #include <QtCore>
#include "ui_configuration_list_widget.h"
#include <memory> #include <memory>
#include "ui_configuration_list_widget.h"
constexpr char CONF_FILE_NAME[] = "Kyty.ini"; constexpr char CONF_FILE_NAME[] = "Kyty.ini";
constexpr char CONF_ORG_NAME[] = "Kyty"; constexpr char CONF_ORG_NAME[] = "Kyty";
constexpr char CONF_APP_NAME[] = "Kyty"; constexpr char CONF_APP_NAME[] = "Kyty";
+15 -8
View File
@@ -6,10 +6,10 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/stringUtils.h" #include "common/stringUtils.h"
#include "common/virtualMemory.h" #include "common/virtualMemory.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/graphicsRun.h" #include "graphics/guest_gpu/graphicsRun.h"
#include "graphics/guest_gpu/hardwareContext.h" #include "graphics/guest_gpu/hardwareContext.h"
#include "graphics/guest_gpu/pm4.h" #include "graphics/guest_gpu/pm4.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/tile.h" #include "graphics/guest_gpu/tile.h"
#include "graphics/host_gpu/objects/label.h" #include "graphics/host_gpu/objects/label.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
@@ -575,8 +575,12 @@ static bool get_shader_program_address_register(uint8_t type, uint32_t* lo_offse
case Prospero::ShaderBinaryType::kPs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_PS; return true; case Prospero::ShaderBinaryType::kPs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_PS; return true;
case Prospero::ShaderBinaryType::kGs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_ES; return true; case Prospero::ShaderBinaryType::kGs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_ES; return true;
case Prospero::ShaderBinaryType::kHs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_LS; return true; case Prospero::ShaderBinaryType::kHs: *lo_offset = Pm4::SPI_SHADER_PGM_LO_LS; return true;
case Prospero::ShaderBinaryType::kGsBack: *lo_offset = Pm4::SPI_SHADER_PGM_LO_GS; return true; case Prospero::ShaderBinaryType::kGsBack:
case Prospero::ShaderBinaryType::kHsBack: *lo_offset = Pm4::SPI_SHADER_PGM_LO_HS; return true; *lo_offset = Pm4::SPI_SHADER_PGM_LO_GS;
return true;
case Prospero::ShaderBinaryType::kHsBack:
*lo_offset = Pm4::SPI_SHADER_PGM_LO_HS;
return true;
case Prospero::ShaderBinaryType::kGsFront: case Prospero::ShaderBinaryType::kGsFront:
case Prospero::ShaderBinaryType::kHsFront: case Prospero::ShaderBinaryType::kHsFront:
case Prospero::ShaderBinaryType::kFs: return false; case Prospero::ShaderBinaryType::kFs: return false;
@@ -1016,12 +1020,14 @@ int KYTY_SYSV_ABI GraphicsSetUcRegIndirectPatchAddRegisters(uint32_t* cmd, uint3
static uint32_t GraphicsPrimitiveTypeToGsOut(uint32_t prim_type) { static uint32_t GraphicsPrimitiveTypeToGsOut(uint32_t prim_type) {
switch (static_cast<Prospero::PrimitiveType>(prim_type)) { switch (static_cast<Prospero::PrimitiveType>(prim_type)) {
case Prospero::PrimitiveType::kPointList: return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::kPoints); case Prospero::PrimitiveType::kPointList:
return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::kPoints);
case Prospero::PrimitiveType::kLineList: case Prospero::PrimitiveType::kLineList:
case Prospero::PrimitiveType::kLineStrip: case Prospero::PrimitiveType::kLineStrip:
case Prospero::PrimitiveType::kLineListAdjacency: case Prospero::PrimitiveType::kLineListAdjacency:
case Prospero::PrimitiveType::kLineStripAdjacency: case Prospero::PrimitiveType::kLineStripAdjacency:
case Prospero::PrimitiveType::kLineLoop: return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::kLines); case Prospero::PrimitiveType::kLineLoop:
return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::kLines);
case Prospero::PrimitiveType::kRectList: case Prospero::PrimitiveType::kRectList:
return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::k2dRectangle); return Prospero::GpuEnumValue(Prospero::GsOutputPrimitiveType::k2dRectangle);
case Prospero::PrimitiveType::kRectListLegacy: case Prospero::PrimitiveType::kRectListLegacy:
@@ -1048,9 +1054,10 @@ int KYTY_SYSV_ABI GraphicsCreatePrimState(ShaderRegister* cx_regs, ShaderRegiste
EXIT_NOT_IMPLEMENTED(gs == nullptr); EXIT_NOT_IMPLEMENTED(gs == nullptr);
EXIT_NOT_IMPLEMENTED(hs != nullptr && EXIT_NOT_IMPLEMENTED(hs != nullptr && static_cast<Prospero::ShaderBinaryType>(hs->type) !=
static_cast<Prospero::ShaderBinaryType>(hs->type) != Prospero::ShaderBinaryType::kHs); Prospero::ShaderBinaryType::kHs);
EXIT_NOT_IMPLEMENTED(static_cast<Prospero::ShaderBinaryType>(gs->type) != Prospero::ShaderBinaryType::kGs); EXIT_NOT_IMPLEMENTED(static_cast<Prospero::ShaderBinaryType>(gs->type) !=
Prospero::ShaderBinaryType::kGs);
if (cx_regs != nullptr) { if (cx_regs != nullptr) {
EXIT_NOT_IMPLEMENTED(hs != nullptr && hs->specials->vgt_shader_stages_en.offset != EXIT_NOT_IMPLEMENTED(hs != nullptr && hs->specials->vgt_shader_stages_en.offset !=
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -366,7 +366,7 @@ static void audioout2_queue_context_audio(AudioOut2ContextHandle ctx, bool block
} }
(void)AudioInternal::AudioOutOutputs(params.data(), static_cast<uint32_t>(params.size()), (void)AudioInternal::AudioOutOutputs(params.data(), static_cast<uint32_t>(params.size()),
blocking); blocking);
} }
static void audioout2_close_audio_handle(int audio_handle) { static void audioout2_close_audio_handle(int audio_handle) {