mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-03 11:23:49 +00:00
graphics: unify buffer bindings and depth target handling
This commit is contained in:
@@ -597,30 +597,7 @@ KYTY_HW_CTX_PARSER(HwCtxSetDepthRenderTarget) {
|
|||||||
uint32_t count = 1;
|
uint32_t count = 1;
|
||||||
|
|
||||||
if (cmd_id == 0xC0016900) {
|
if (cmd_id == 0xC0016900) {
|
||||||
HW::DepthZInfo r;
|
cp.GetCtx().SetDepthZInfo(HW::DepthZInfo::Decode(buffer[0]));
|
||||||
|
|
||||||
// r.expclear_enabled = (buffer[0] & 0x08000000u) != 0;
|
|
||||||
// r.format = (buffer[0] >> Pm4::DB_Z_INFO_FORMAT_SHIFT) &
|
|
||||||
// Pm4::DB_Z_INFO_FORMAT_MASK; r.num_samples = (buffer[0] >>
|
|
||||||
// Pm4::DB_Z_INFO_NUM_SAMPLES_SHIFT) & Pm4::DB_Z_INFO_NUM_SAMPLES_MASK; r.tile_mode_index =
|
|
||||||
//(buffer[0] >> Pm4::DB_Z_INFO_TILE_MODE_INDEX_SHIFT) & Pm4::DB_Z_INFO_TILE_MODE_INDEX_MASK;
|
|
||||||
// r.tile_surface_enable = ((buffer[0] >> Pm4::DB_Z_INFO_TILE_SURFACE_ENABLE_SHIFT) &
|
|
||||||
// Pm4::DB_Z_INFO_TILE_SURFACE_ENABLE_MASK) !=0
|
|
||||||
// r.zrange_precision = (buffer[0] >> Pm4::DB_Z_INFO_ZRANGE_PRECISION_SHIFT) &
|
|
||||||
// Pm4::DB_Z_INFO_ZRANGE_PRECISION_MASK;
|
|
||||||
|
|
||||||
r.format = KYTY_PM4_GET(buffer[0], DB_Z_INFO, FORMAT);
|
|
||||||
r.num_samples = KYTY_PM4_GET(buffer[0], DB_Z_INFO, NUM_SAMPLES);
|
|
||||||
r.embedded_sample_locations = KYTY_PM4_GET(buffer[0], DB_Z_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
r.partially_resident = KYTY_PM4_GET(buffer[0], DB_Z_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
r.num_mip_levels = KYTY_PM4_GET(buffer[0], DB_Z_INFO, MAXMIP);
|
|
||||||
r.tile_mode_index = KYTY_PM4_GET(buffer[0], DB_Z_INFO, TILE_MODE_INDEX);
|
|
||||||
r.plane_compression = KYTY_PM4_GET(buffer[0], DB_Z_INFO, DECOMPRESS_ON_N_ZPLANES);
|
|
||||||
r.expclear_enabled = KYTY_PM4_GET(buffer[0], DB_Z_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
r.tile_surface_enable = KYTY_PM4_GET(buffer[0], DB_Z_INFO, TILE_SURFACE_ENABLE) != 0;
|
|
||||||
r.zrange_precision = KYTY_PM4_GET(buffer[0], DB_Z_INFO, ZRANGE_PRECISION);
|
|
||||||
|
|
||||||
cp.GetCtx().SetDepthZInfo(r);
|
|
||||||
} else if (cmd_id == 0xC0086900) {
|
} else if (cmd_id == 0xC0086900) {
|
||||||
if (dw >= 22 && buffer[8] == 0xC0016900 && buffer[9] == Pm4::DB_DEPTH_INFO &&
|
if (dw >= 22 && buffer[8] == 0xC0016900 && buffer[9] == Pm4::DB_DEPTH_INFO &&
|
||||||
buffer[11] == 0xC0016900 && buffer[12] == Pm4::DB_DEPTH_VIEW &&
|
buffer[11] == 0xC0016900 && buffer[12] == Pm4::DB_DEPTH_VIEW &&
|
||||||
@@ -631,51 +608,8 @@ KYTY_HW_CTX_PARSER(HwCtxSetDepthRenderTarget) {
|
|||||||
|
|
||||||
HW::DepthRenderTarget z;
|
HW::DepthRenderTarget z;
|
||||||
|
|
||||||
// z.z_info.expclear_enabled = (buffer[0] & 0x08000000u) != 0;
|
z.z_info = HW::DepthZInfo::Decode(buffer[0]);
|
||||||
// z.z_info.format = (buffer[0] >> Pm4::DB_Z_INFO_FORMAT_SHIFT) &
|
z.stencil_info = HW::DepthStencilInfo::Decode(buffer[1]);
|
||||||
// Pm4::DB_Z_INFO_FORMAT_MASK; z.z_info.num_samples = (buffer[0] >>
|
|
||||||
// Pm4::DB_Z_INFO_NUM_SAMPLES_SHIFT) & Pm4::DB_Z_INFO_NUM_SAMPLES_MASK;
|
|
||||||
// z.z_info.tile_mode_index = (buffer[0] >>
|
|
||||||
// Pm4::DB_Z_INFO_TILE_MODE_INDEX_SHIFT) &
|
|
||||||
// Pm4::DB_Z_INFO_TILE_MODE_INDEX_MASK; z.z_info.tile_surface_enable =
|
|
||||||
// KYTY_PM4_GET(buffer[0], DB_Z_INFO, TILE_SURFACE_ENABLE) != 0;
|
|
||||||
// z.z_info.zrange_precision = (buffer[0] >> Pm4::DB_Z_INFO_ZRANGE_PRECISION_SHIFT) &
|
|
||||||
// Pm4::DB_Z_INFO_ZRANGE_PRECISION_MASK;
|
|
||||||
|
|
||||||
z.z_info.format = KYTY_PM4_GET(buffer[0], DB_Z_INFO, FORMAT);
|
|
||||||
z.z_info.num_samples = KYTY_PM4_GET(buffer[0], DB_Z_INFO, NUM_SAMPLES);
|
|
||||||
z.z_info.embedded_sample_locations =
|
|
||||||
KYTY_PM4_GET(buffer[0], DB_Z_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
z.z_info.partially_resident =
|
|
||||||
KYTY_PM4_GET(buffer[0], DB_Z_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
z.z_info.num_mip_levels = KYTY_PM4_GET(buffer[0], DB_Z_INFO, MAXMIP);
|
|
||||||
z.z_info.tile_mode_index = KYTY_PM4_GET(buffer[0], DB_Z_INFO, TILE_MODE_INDEX);
|
|
||||||
z.z_info.plane_compression =
|
|
||||||
KYTY_PM4_GET(buffer[0], DB_Z_INFO, DECOMPRESS_ON_N_ZPLANES);
|
|
||||||
z.z_info.expclear_enabled = KYTY_PM4_GET(buffer[0], DB_Z_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
z.z_info.tile_surface_enable =
|
|
||||||
KYTY_PM4_GET(buffer[0], DB_Z_INFO, TILE_SURFACE_ENABLE) != 0;
|
|
||||||
z.z_info.zrange_precision = KYTY_PM4_GET(buffer[0], DB_Z_INFO, ZRANGE_PRECISION);
|
|
||||||
|
|
||||||
// z.stencil_info.expclear_enabled = (buffer[1] & 0x08000000u) != 0;
|
|
||||||
// z.stencil_info.tile_split = (buffer[1] >> 13u) & 0x7u;
|
|
||||||
// z.stencil_info.format = KYTY_PM4_GET(buffer[1],
|
|
||||||
// DB_STENCIL_INFO, FORMAT); z.stencil_info.tile_mode_index =
|
|
||||||
// KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_MODE_INDEX);
|
|
||||||
// z.stencil_info.tile_stencil_disable = KYTY_PM4_GET(buffer[1],
|
|
||||||
// DB_STENCIL_INFO, TILE_STENCIL_DISABLE);
|
|
||||||
z.stencil_info.format = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, FORMAT);
|
|
||||||
z.stencil_info.texture_compatible_stencil =
|
|
||||||
KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
z.stencil_info.partially_resident =
|
|
||||||
KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
z.stencil_info.tile_split = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, RESERVED_FIELD_1);
|
|
||||||
z.stencil_info.tile_mode_index =
|
|
||||||
KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_MODE_INDEX);
|
|
||||||
z.stencil_info.expclear_enabled =
|
|
||||||
KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
z.stencil_info.tile_stencil_disable =
|
|
||||||
KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_STENCIL_DISABLE) != 0;
|
|
||||||
|
|
||||||
z.z_read_base_addr = static_cast<uint64_t>(buffer[2]) << 8u;
|
z.z_read_base_addr = static_cast<uint64_t>(buffer[2]) << 8u;
|
||||||
z.stencil_read_base_addr = static_cast<uint64_t>(buffer[3]) << 8u;
|
z.stencil_read_base_addr = static_cast<uint64_t>(buffer[3]) << 8u;
|
||||||
@@ -1252,26 +1186,7 @@ KYTY_HW_CTX_PARSER(HwCtxSetStencilInfo) {
|
|||||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900);
|
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900);
|
||||||
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_STENCIL_INFO);
|
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_STENCIL_INFO);
|
||||||
|
|
||||||
HW::DepthStencilInfo r;
|
cp.GetCtx().SetDepthStencilInfo(HW::DepthStencilInfo::Decode(buffer[0]));
|
||||||
|
|
||||||
// r.expclear_enabled = (buffer[0] & 0x08000000u) != 0;
|
|
||||||
// r.tile_split = (buffer[0] >> 13u) & 0x7u;
|
|
||||||
// r.format = (buffer[0] >> Pm4::DB_STENCIL_INFO_FORMAT_SHIFT) &
|
|
||||||
// Pm4::DB_STENCIL_INFO_FORMAT_MASK; r.tile_mode_index = (buffer[0] >>
|
|
||||||
// Pm4::DB_STENCIL_INFO_TILE_MODE_INDEX_SHIFT) & Pm4::DB_STENCIL_INFO_TILE_MODE_INDEX_MASK;
|
|
||||||
// r.tile_stencil_disable =
|
|
||||||
// ((buffer[0] >> Pm4::DB_STENCIL_INFO_TILE_STENCIL_DISABLE_SHIFT) &
|
|
||||||
// Pm4::DB_STENCIL_INFO_TILE_STENCIL_DISABLE_MASK) != 0;
|
|
||||||
|
|
||||||
r.format = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, FORMAT);
|
|
||||||
r.texture_compatible_stencil = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
r.partially_resident = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
r.tile_split = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, RESERVED_FIELD_1);
|
|
||||||
r.tile_mode_index = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_MODE_INDEX);
|
|
||||||
r.expclear_enabled = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
r.tile_stencil_disable = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_STENCIL_DISABLE) != 0;
|
|
||||||
|
|
||||||
cp.GetCtx().SetDepthStencilInfo(r);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -3757,18 +3672,7 @@ void GraphicsInitJmpTablesCxIndirect() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
g_hw_ctx_indirect_func[Pm4::DB_Z_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
g_hw_ctx_indirect_func[Pm4::DB_Z_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||||
HW::DepthZInfo r;
|
cp.GetCtx().SetDepthZInfo(HW::DepthZInfo::Decode(value));
|
||||||
r.format = KYTY_PM4_GET(value, DB_Z_INFO, FORMAT);
|
|
||||||
r.num_samples = KYTY_PM4_GET(value, DB_Z_INFO, NUM_SAMPLES);
|
|
||||||
r.embedded_sample_locations = KYTY_PM4_GET(value, DB_Z_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
r.partially_resident = KYTY_PM4_GET(value, DB_Z_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
r.num_mip_levels = KYTY_PM4_GET(value, DB_Z_INFO, MAXMIP);
|
|
||||||
r.tile_mode_index = KYTY_PM4_GET(value, DB_Z_INFO, TILE_MODE_INDEX);
|
|
||||||
r.plane_compression = KYTY_PM4_GET(value, DB_Z_INFO, DECOMPRESS_ON_N_ZPLANES);
|
|
||||||
r.expclear_enabled = KYTY_PM4_GET(value, DB_Z_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
r.tile_surface_enable = KYTY_PM4_GET(value, DB_Z_INFO, TILE_SURFACE_ENABLE) != 0;
|
|
||||||
r.zrange_precision = KYTY_PM4_GET(value, DB_Z_INFO, ZRANGE_PRECISION);
|
|
||||||
cp.GetCtx().SetDepthZInfo(r);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
g_hw_ctx_indirect_func[Pm4::DB_DEPTH_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
g_hw_ctx_indirect_func[Pm4::DB_DEPTH_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||||
@@ -3796,15 +3700,7 @@ void GraphicsInitJmpTablesCxIndirect() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
g_hw_ctx_indirect_func[Pm4::DB_STENCIL_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
g_hw_ctx_indirect_func[Pm4::DB_STENCIL_INFO] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||||
HW::DepthStencilInfo r;
|
cp.GetCtx().SetDepthStencilInfo(HW::DepthStencilInfo::Decode(value));
|
||||||
r.format = KYTY_PM4_GET(value, DB_STENCIL_INFO, FORMAT);
|
|
||||||
r.texture_compatible_stencil = KYTY_PM4_GET(value, DB_STENCIL_INFO, ITERATE_FLUSH) != 0;
|
|
||||||
r.partially_resident = KYTY_PM4_GET(value, DB_STENCIL_INFO, PARTIALLY_RESIDENT) != 0;
|
|
||||||
r.tile_split = KYTY_PM4_GET(value, DB_STENCIL_INFO, RESERVED_FIELD_1);
|
|
||||||
r.tile_mode_index = KYTY_PM4_GET(value, DB_STENCIL_INFO, TILE_MODE_INDEX);
|
|
||||||
r.expclear_enabled = KYTY_PM4_GET(value, DB_STENCIL_INFO, ALLOW_EXPCLEAR) != 0;
|
|
||||||
r.tile_stencil_disable = KYTY_PM4_GET(value, DB_STENCIL_INFO, TILE_STENCIL_DISABLE) != 0;
|
|
||||||
cp.GetCtx().SetDepthStencilInfo(r);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
g_hw_ctx_indirect_func[Pm4::DB_Z_READ_BASE] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
g_hw_ctx_indirect_func[Pm4::DB_Z_READ_BASE] = [](KYTY_HW_CTX_INDIRECT_ARGS) {
|
||||||
|
|||||||
@@ -142,6 +142,24 @@ enum class StencilFormat : uint32_t {
|
|||||||
k8UInt = 1,
|
k8UInt = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TextureCompatiblePlaneCompression : uint32_t {
|
||||||
|
kDisable = 0x00000000,
|
||||||
|
kEnable = 0x02900800,
|
||||||
|
kBitMask = 0x02900800,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TextureCompatibleStencil : uint32_t {
|
||||||
|
kDisable = 0x00000000,
|
||||||
|
kEnable = 0x00100800,
|
||||||
|
kBitMask = 0x00100800,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ZCompareBase : uint32_t {
|
||||||
|
kZMin = 0x00000000,
|
||||||
|
kZMax = 0x80000000,
|
||||||
|
kBitMask = 0x80000000,
|
||||||
|
};
|
||||||
|
|
||||||
enum class TileMode : uint32_t {
|
enum class TileMode : uint32_t {
|
||||||
kLinear = 0x00,
|
kLinear = 0x00,
|
||||||
kStandard256B = 0x01,
|
kStandard256B = 0x01,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "common/abi.h"
|
#include "common/abi.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
#include "graphics/guest_gpu/gpu_defs.h"
|
||||||
|
|
||||||
namespace Libs::Graphics::HW {
|
namespace Libs::Graphics::HW {
|
||||||
|
|
||||||
@@ -131,26 +132,66 @@ struct RenderTarget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct DepthZInfo {
|
struct DepthZInfo {
|
||||||
uint32_t format = 0;
|
uint32_t format = 0;
|
||||||
uint32_t tile_mode_index = 0;
|
uint32_t num_samples = 0;
|
||||||
uint32_t num_samples = 0;
|
Prospero::TextureCompatiblePlaneCompression texture_compatibility =
|
||||||
uint32_t zrange_precision = 0;
|
Prospero::TextureCompatiblePlaneCompression::kDisable;
|
||||||
bool tile_surface_enable = false;
|
Prospero::ZCompareBase z_compare_base = Prospero::ZCompareBase::kZMin;
|
||||||
bool expclear_enabled = false;
|
bool htile_acceleration = false;
|
||||||
bool embedded_sample_locations = false;
|
bool expclear_enabled = false;
|
||||||
bool partially_resident = false;
|
bool partially_resident = false;
|
||||||
uint8_t num_mip_levels = 0;
|
uint8_t max_mip_level = 0;
|
||||||
uint8_t plane_compression = 0;
|
|
||||||
|
[[nodiscard]] static DepthZInfo Decode(uint32_t value) {
|
||||||
|
DepthZInfo info;
|
||||||
|
info.format = value & 0x3u;
|
||||||
|
info.num_samples = (value >> 2u) & 0x3u;
|
||||||
|
info.texture_compatibility = static_cast<Prospero::TextureCompatiblePlaneCompression>(
|
||||||
|
value & Prospero::GpuEnumValue(Prospero::TextureCompatiblePlaneCompression::kBitMask));
|
||||||
|
info.partially_resident = (value & 0x00001000u) != 0;
|
||||||
|
info.max_mip_level = static_cast<uint8_t>((value >> 16u) & 0x0fu);
|
||||||
|
info.expclear_enabled = (value & 0x08000000u) != 0;
|
||||||
|
info.htile_acceleration = (value & 0x20000000u) != 0;
|
||||||
|
info.z_compare_base = static_cast<Prospero::ZCompareBase>(
|
||||||
|
value & Prospero::GpuEnumValue(Prospero::ZCompareBase::kBitMask));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasValidTextureCompatibility() const {
|
||||||
|
switch (texture_compatibility) {
|
||||||
|
case Prospero::TextureCompatiblePlaneCompression::kDisable:
|
||||||
|
case Prospero::TextureCompatiblePlaneCompression::kEnable: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DepthStencilInfo {
|
struct DepthStencilInfo {
|
||||||
uint32_t format = 0;
|
uint32_t format = 0;
|
||||||
uint32_t tile_mode_index = 0;
|
Prospero::TextureCompatibleStencil texture_compatibility =
|
||||||
uint32_t tile_split = 0;
|
Prospero::TextureCompatibleStencil::kDisable;
|
||||||
bool expclear_enabled = false;
|
bool expclear_enabled = false;
|
||||||
bool tile_stencil_disable = false;
|
bool htile_stencil_disabled = false;
|
||||||
bool texture_compatible_stencil = false;
|
bool partially_resident = false;
|
||||||
bool partially_resident = false;
|
|
||||||
|
[[nodiscard]] static DepthStencilInfo Decode(uint32_t value) {
|
||||||
|
DepthStencilInfo info;
|
||||||
|
info.format = value & 0x1u;
|
||||||
|
info.texture_compatibility = static_cast<Prospero::TextureCompatibleStencil>(
|
||||||
|
value & Prospero::GpuEnumValue(Prospero::TextureCompatibleStencil::kBitMask));
|
||||||
|
info.partially_resident = (value & 0x00001000u) != 0;
|
||||||
|
info.expclear_enabled = (value & 0x08000000u) != 0;
|
||||||
|
info.htile_stencil_disabled = (value & 0x20000000u) != 0;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasValidTextureCompatibility() const {
|
||||||
|
switch (texture_compatibility) {
|
||||||
|
case Prospero::TextureCompatibleStencil::kDisable:
|
||||||
|
case Prospero::TextureCompatibleStencil::kEnable: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DepthRenderTargetDepthInfo {
|
struct DepthRenderTargetDepthInfo {
|
||||||
|
|||||||
@@ -430,21 +430,17 @@ static void ZPrint(const char* func, const HW::DepthRenderTarget& z) {
|
|||||||
LOGF("%s\n", func);
|
LOGF("%s\n", func);
|
||||||
|
|
||||||
LOGF("\t z_info.format = 0x%08" PRIx32 "\n"
|
LOGF("\t z_info.format = 0x%08" PRIx32 "\n"
|
||||||
"\t z_info.tile_mode_index = 0x%08" PRIx32 "\n"
|
|
||||||
"\t z_info.num_samples = 0x%08" PRIx32 "\n"
|
"\t z_info.num_samples = 0x%08" PRIx32 "\n"
|
||||||
"\t z_info.tile_surface_enable = %s\n"
|
"\t z_info.texture_compatibility = 0x%08" PRIx32 "\n"
|
||||||
|
"\t z_info.htile_acceleration = %s\n"
|
||||||
"\t z_info.expclear_enabled = %s\n"
|
"\t z_info.expclear_enabled = %s\n"
|
||||||
"\t z_info.zrange_precision = 0x%08" PRIx32 "\n"
|
"\t z_info.z_compare_base = 0x%08" PRIx32 "\n"
|
||||||
"\t z_info.embedded_sample_locations = %s\n"
|
|
||||||
"\t z_info.partially_resident = %s\n"
|
"\t z_info.partially_resident = %s\n"
|
||||||
"\t z_info.num_mip_levels = 0x%02" PRIx8 "\n"
|
"\t z_info.max_mip_level = 0x%02" PRIx8 "\n"
|
||||||
"\t z_info.plane_compression = 0x%02" PRIx8 "\n"
|
|
||||||
"\t stencil_info.format = 0x%08" PRIx32 "\n"
|
"\t stencil_info.format = 0x%08" PRIx32 "\n"
|
||||||
"\t stencil_info.tile_stencil_disable = %s\n"
|
"\t stencil_info.texture_compatibility = 0x%08" PRIx32 "\n"
|
||||||
|
"\t stencil_info.htile_stencil_disabled = %s\n"
|
||||||
"\t stencil_info.expclear_enabled = %s\n"
|
"\t stencil_info.expclear_enabled = %s\n"
|
||||||
"\t stencil_info.tile_mode_index = 0x%08" PRIx32 "\n"
|
|
||||||
"\t stencil_info.tile_split = 0x%08" PRIx32 "\n"
|
|
||||||
"\t stencil_info.texture_compatible_stencil = %s\n"
|
|
||||||
"\t stencil_info.partially_resident = %s\n"
|
"\t stencil_info.partially_resident = %s\n"
|
||||||
"\t depth_info.addr5_swizzle_mask = 0x%08" PRIx32 "\n"
|
"\t depth_info.addr5_swizzle_mask = 0x%08" PRIx32 "\n"
|
||||||
"\t depth_info.array_mode = 0x%08" PRIx32 "\n"
|
"\t depth_info.array_mode = 0x%08" PRIx32 "\n"
|
||||||
@@ -477,15 +473,15 @@ static void ZPrint(const char* func, const HW::DepthRenderTarget& z) {
|
|||||||
"\t height = 0x%08" PRIx32 "\n"
|
"\t height = 0x%08" PRIx32 "\n"
|
||||||
"\t size.x_max = 0x%04" PRIx16 "\n"
|
"\t size.x_max = 0x%04" PRIx16 "\n"
|
||||||
"\t size.y_max = 0x%04" PRIx16 "\n",
|
"\t size.y_max = 0x%04" PRIx16 "\n",
|
||||||
z.z_info.format, z.z_info.tile_mode_index, z.z_info.num_samples,
|
z.z_info.format, z.z_info.num_samples,
|
||||||
z.z_info.tile_surface_enable ? "true" : "false",
|
Prospero::GpuEnumValue(z.z_info.texture_compatibility),
|
||||||
z.z_info.expclear_enabled ? "true" : "false", z.z_info.zrange_precision,
|
z.z_info.htile_acceleration ? "true" : "false",
|
||||||
z.z_info.embedded_sample_locations ? "true" : "false",
|
z.z_info.expclear_enabled ? "true" : "false",
|
||||||
z.z_info.partially_resident ? "true" : "false", z.z_info.num_mip_levels,
|
Prospero::GpuEnumValue(z.z_info.z_compare_base),
|
||||||
z.z_info.plane_compression, z.stencil_info.format,
|
z.z_info.partially_resident ? "true" : "false", z.z_info.max_mip_level,
|
||||||
z.stencil_info.tile_stencil_disable ? "true" : "false",
|
z.stencil_info.format, Prospero::GpuEnumValue(z.stencil_info.texture_compatibility),
|
||||||
z.stencil_info.expclear_enabled ? "true" : "false", z.stencil_info.tile_mode_index,
|
z.stencil_info.htile_stencil_disabled ? "true" : "false",
|
||||||
z.stencil_info.tile_split, z.stencil_info.texture_compatible_stencil ? "true" : "false",
|
z.stencil_info.expclear_enabled ? "true" : "false",
|
||||||
z.stencil_info.partially_resident ? "true" : "false", z.depth_info.addr5_swizzle_mask,
|
z.stencil_info.partially_resident ? "true" : "false", z.depth_info.addr5_swizzle_mask,
|
||||||
z.depth_info.array_mode, z.depth_info.pipe_config, z.depth_info.bank_width,
|
z.depth_info.array_mode, z.depth_info.pipe_config, z.depth_info.bank_width,
|
||||||
z.depth_info.bank_height, z.depth_info.macro_tile_aspect, z.depth_info.num_banks,
|
z.depth_info.bank_height, z.depth_info.macro_tile_aspect, z.depth_info.num_banks,
|
||||||
@@ -502,36 +498,17 @@ static void ZPrint(const char* func, const HW::DepthRenderTarget& z) {
|
|||||||
|
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
static void ZCheck(const HW::DepthRenderTarget& z) {
|
static void ZCheck(const HW::DepthRenderTarget& z) {
|
||||||
|
EXIT_NOT_IMPLEMENTED(!z.z_info.HasValidTextureCompatibility());
|
||||||
|
EXIT_NOT_IMPLEMENTED(!z.stencil_info.HasValidTextureCompatibility());
|
||||||
if (z.z_info.format == 0) {
|
if (z.z_info.format == 0) {
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.format != 0);
|
EXIT_NOT_IMPLEMENTED(z.z_info.format != 0);
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.tile_mode_index != 0);
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.num_samples != 0);
|
EXIT_NOT_IMPLEMENTED(z.z_info.num_samples != 0);
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.tile_surface_enable != false);
|
EXIT_NOT_IMPLEMENTED(z.z_info.htile_acceleration != false);
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false);
|
EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false);
|
||||||
if (z.z_info.zrange_precision != 0) {
|
|
||||||
LOGF("Warning: zrange_precision != 0\n");
|
|
||||||
// z.z_info.zrange_precision = 0;
|
|
||||||
}
|
|
||||||
if (z.z_info.embedded_sample_locations) {
|
|
||||||
static bool logged = false;
|
|
||||||
if (!logged) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring embedded sample locations\n");
|
|
||||||
logged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false);
|
EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false);
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.num_mip_levels != 0);
|
EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 0);
|
||||||
if (z.z_info.plane_compression != 0) {
|
|
||||||
static bool logged = false;
|
|
||||||
if (!logged) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring PS5 plane_compression=0x%02" PRIx8 "\n",
|
|
||||||
z.z_info.plane_compression);
|
|
||||||
logged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.format != 0x00000001 && z.z_info.format != 0x00000003);
|
EXIT_NOT_IMPLEMENTED(z.z_info.format != 0x00000001 && z.z_info.format != 0x00000003);
|
||||||
// EXIT_NOT_IMPLEMENTED(z.z_info.tile_mode_index != 0x00000002);
|
|
||||||
if (z.z_info.num_samples != 0x00000000) {
|
if (z.z_info.num_samples != 0x00000000) {
|
||||||
static bool logged = false;
|
static bool logged = false;
|
||||||
if (!logged) {
|
if (!logged) {
|
||||||
@@ -540,56 +517,17 @@ static void ZCheck(const HW::DepthRenderTarget& z) {
|
|||||||
logged = true;
|
logged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// EXIT_NOT_IMPLEMENTED(z.z_info.tile_surface_enable != true);
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false);
|
EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false);
|
||||||
if (z.z_info.zrange_precision != 0x00000001) {
|
|
||||||
static bool logged = false;
|
|
||||||
if (!logged) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring zrange_precision=0x%08" PRIx32 "\n",
|
|
||||||
z.z_info.zrange_precision);
|
|
||||||
logged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (z.z_info.embedded_sample_locations) {
|
|
||||||
static bool logged = false;
|
|
||||||
if (!logged) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring embedded sample locations\n");
|
|
||||||
logged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false);
|
EXIT_NOT_IMPLEMENTED(z.z_info.partially_resident != false);
|
||||||
EXIT_NOT_IMPLEMENTED(z.z_info.num_mip_levels != 0);
|
EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 0);
|
||||||
if (z.z_info.plane_compression != 0) {
|
|
||||||
static bool logged = false;
|
|
||||||
if (!logged) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring PS5 plane_compression=0x%02" PRIx8 "\n",
|
|
||||||
z.z_info.plane_compression);
|
|
||||||
logged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (z.stencil_info.format == 0) {
|
if (z.stencil_info.format == 0) {
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.format != 0);
|
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.tile_stencil_disable != false);
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.stencil_info.expclear_enabled != false);
|
EXIT_NOT_IMPLEMENTED(z.stencil_info.expclear_enabled != false);
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.tile_mode_index != 0);
|
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.tile_split != 0);
|
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.texture_compatible_stencil != true);
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.stencil_info.partially_resident != false);
|
EXIT_NOT_IMPLEMENTED(z.stencil_info.partially_resident != false);
|
||||||
} else {
|
} else {
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.format != 0x00000001);
|
EXIT_NOT_IMPLEMENTED(z.stencil_info.format != 0x00000001);
|
||||||
if (z.stencil_info.tile_stencil_disable != true) {
|
|
||||||
|
|
||||||
static std::atomic<uint32_t> log_count {0};
|
|
||||||
if (log_count.fetch_add(1) < 16) {
|
|
||||||
LOGF("DepthTarget: temporary: ignoring PS5 HTILE stencil acceleration\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.stencil_info.expclear_enabled != false);
|
EXIT_NOT_IMPLEMENTED(z.stencil_info.expclear_enabled != false);
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.tile_mode_index != 0x00000002);
|
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.tile_split != 0x00000002);
|
|
||||||
// EXIT_NOT_IMPLEMENTED(z.stencil_info.texture_compatible_stencil != true);
|
|
||||||
EXIT_NOT_IMPLEMENTED(z.stencil_info.partially_resident != false);
|
EXIT_NOT_IMPLEMENTED(z.stencil_info.partially_resident != false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ static bool UsesStencilOpValue(uint8_t fail, uint8_t pass, uint8_t depth_fail) {
|
|||||||
|
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandBuffer& buffer,
|
void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandBuffer& buffer,
|
||||||
RenderDepthInfo& r) {
|
RenderDepthInfo& r) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
(void)submit_id;
|
(void)submit_id;
|
||||||
const auto& hw = buffer.GetRegisters();
|
const auto& hw = buffer.GetRegisters();
|
||||||
@@ -102,31 +102,34 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
if (!depth_active && !stencil_active) {
|
if (!depth_active && !stencil_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!z.z_info.HasValidTextureCompatibility() ||
|
||||||
|
!z.stencil_info.HasValidTextureCompatibility()) {
|
||||||
|
DepthFatal("invalid PS5 depth texture-compatibility encoding");
|
||||||
|
}
|
||||||
const bool attachment_unbound =
|
const bool attachment_unbound =
|
||||||
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kInvalid) &&
|
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kInvalid) &&
|
||||||
z.stencil_info.format == Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid) &&
|
z.stencil_info.format == Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid) &&
|
||||||
z.z_info.tile_mode_index == 0 && z.z_info.num_samples == 0 &&
|
z.z_info.num_samples == 0 &&
|
||||||
z.z_info.zrange_precision <= 1 && !z.z_info.expclear_enabled &&
|
z.z_info.texture_compatibility == Prospero::TextureCompatiblePlaneCompression::kDisable &&
|
||||||
!z.z_info.embedded_sample_locations && !z.z_info.partially_resident &&
|
!z.z_info.expclear_enabled && !z.z_info.partially_resident && z.z_info.max_mip_level == 0 &&
|
||||||
z.z_info.num_mip_levels == 0 && z.z_info.plane_compression == 0 &&
|
z.stencil_info.texture_compatibility == Prospero::TextureCompatibleStencil::kDisable &&
|
||||||
z.stencil_info.tile_mode_index == 0 && z.stencil_info.tile_split == 0 &&
|
!z.stencil_info.expclear_enabled && !z.stencil_info.partially_resident &&
|
||||||
!z.stencil_info.expclear_enabled && !z.stencil_info.texture_compatible_stencil &&
|
z.depth_view.slice_start == 0 && z.depth_view.slice_max == 0 &&
|
||||||
!z.stencil_info.partially_resident && z.depth_view.slice_start == 0 &&
|
z.depth_view.current_mip_level == 0 && !z.depth_view.depth_write_disable &&
|
||||||
z.depth_view.slice_max == 0 && z.depth_view.current_mip_level == 0 &&
|
!z.depth_view.stencil_write_disable && z.depth_info.addr5_swizzle_mask == 0 &&
|
||||||
!z.depth_view.depth_write_disable && !z.depth_view.stencil_write_disable &&
|
z.depth_info.array_mode == 0 && z.depth_info.pipe_config == 0 &&
|
||||||
z.depth_info.addr5_swizzle_mask == 0 && z.depth_info.array_mode == 0 &&
|
z.depth_info.bank_width == 0 && z.depth_info.bank_height == 0 &&
|
||||||
z.depth_info.pipe_config == 0 && z.depth_info.bank_width == 0 &&
|
z.depth_info.macro_tile_aspect == 0 && z.depth_info.num_banks == 0 &&
|
||||||
z.depth_info.bank_height == 0 && z.depth_info.macro_tile_aspect == 0 &&
|
z.htile_surface.linear == 0 && z.htile_surface.full_cache == 0 &&
|
||||||
z.depth_info.num_banks == 0 && z.htile_surface.linear == 0 &&
|
z.htile_surface.htile_uses_preload_win == 0 && z.htile_surface.preload == 0 &&
|
||||||
z.htile_surface.full_cache == 0 && z.htile_surface.htile_uses_preload_win == 0 &&
|
z.htile_surface.prefetch_width == 0 && z.htile_surface.prefetch_height == 0 &&
|
||||||
z.htile_surface.preload == 0 && z.htile_surface.prefetch_width == 0 &&
|
z.htile_surface.dst_outside_zero_to_one == 0 && z.z_read_base_addr == 0 &&
|
||||||
z.htile_surface.prefetch_height == 0 && z.htile_surface.dst_outside_zero_to_one == 0 &&
|
z.z_write_base_addr == 0 && z.stencil_read_base_addr == 0 &&
|
||||||
z.z_read_base_addr == 0 && z.z_write_base_addr == 0 && z.stencil_read_base_addr == 0 &&
|
|
||||||
z.stencil_write_base_addr == 0 && z.htile_data_base_addr == 0 &&
|
z.stencil_write_base_addr == 0 && z.htile_data_base_addr == 0 &&
|
||||||
// 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.pitch_height_valid &&
|
!z.z_info.htile_acceleration && !z.width_height_valid && !z.pitch_height_valid &&
|
||||||
z.size.x_max == 0 && z.size.y_max == 0 && z.pitch_div8_minus1 == 0 &&
|
z.size.x_max == 0 && z.size.y_max == 0 && z.pitch_div8_minus1 == 0 &&
|
||||||
z.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 && z.width == 0 && z.height == 0;
|
z.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 && z.width == 0 && z.height == 0;
|
||||||
if (attachment_unbound) {
|
if (attachment_unbound) {
|
||||||
@@ -138,13 +141,13 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
}
|
}
|
||||||
const bool has_stencil =
|
const bool has_stencil =
|
||||||
z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid);
|
z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::kInvalid);
|
||||||
const bool has_htile = z.z_info.tile_surface_enable;
|
const bool has_htile = z.z_info.htile_acceleration;
|
||||||
const auto samples = render_sample_count(z.z_info.num_samples);
|
const auto samples = render_sample_count(z.z_info.num_samples);
|
||||||
if (samples == 0) {
|
if (samples == 0) {
|
||||||
DepthFatal("unsupported depth fragment count: %u", z.z_info.num_samples);
|
DepthFatal("unsupported depth fragment count: %u", z.z_info.num_samples);
|
||||||
}
|
}
|
||||||
const bool htile_stencil_compat = depth_htile_stencil_acceleration_compatible(
|
const bool htile_stencil_compat = depth_htile_stencil_acceleration_compatible(
|
||||||
has_stencil, has_htile, z.stencil_info.tile_stencil_disable);
|
has_stencil, has_htile, z.stencil_info.htile_stencil_disabled);
|
||||||
const auto view = ResolveTargetViewInfo(z.depth_view.slice_start, z.depth_view.slice_max);
|
const auto view = ResolveTargetViewInfo(z.depth_view.slice_start, z.depth_view.slice_max);
|
||||||
switch (view.type) {
|
switch (view.type) {
|
||||||
case TargetViewType::Image2D: break;
|
case TargetViewType::Image2D: break;
|
||||||
@@ -155,14 +158,10 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
DepthFatal("invalid depth view: base=%u last=%u", z.depth_view.slice_start,
|
DepthFatal("invalid depth view: base=%u last=%u", z.depth_view.slice_start,
|
||||||
z.depth_view.slice_max);
|
z.depth_view.slice_max);
|
||||||
}
|
}
|
||||||
// Prospero defines the compression-disable bits as tile writeback policy. Vulkan attachments
|
|
||||||
// expose the same logical depth/stencil values regardless of the driver's backing compression.
|
|
||||||
if ((stencil_active && !has_stencil) || rc.resummarize_enable || rc.copy_centroid ||
|
if ((stencil_active && !has_stencil) || rc.resummarize_enable || rc.copy_centroid ||
|
||||||
rc.copy_sample != 0 || z.z_info.expclear_enabled || z.stencil_info.expclear_enabled ||
|
rc.copy_sample != 0 || z.z_info.expclear_enabled || z.stencil_info.expclear_enabled ||
|
||||||
z.z_info.embedded_sample_locations || z.z_info.partially_resident ||
|
z.z_info.partially_resident || z.stencil_info.partially_resident ||
|
||||||
z.stencil_info.partially_resident || z.z_info.plane_compression != 0 ||
|
z.z_info.max_mip_level != 0 || z.depth_view.current_mip_level != 0 ||
|
||||||
z.z_info.num_mip_levels != 0 || z.z_info.tile_mode_index != 0 ||
|
|
||||||
z.z_info.zrange_precision > 1 || z.depth_view.current_mip_level != 0 ||
|
|
||||||
z.depth_info.addr5_swizzle_mask != 0 || z.depth_info.array_mode != 0 ||
|
z.depth_info.addr5_swizzle_mask != 0 || z.depth_info.array_mode != 0 ||
|
||||||
z.depth_info.pipe_config != 0 || z.depth_info.bank_width != 0 ||
|
z.depth_info.pipe_config != 0 || z.depth_info.bank_width != 0 ||
|
||||||
z.depth_info.bank_height != 0 || z.depth_info.macro_tile_aspect != 0 ||
|
z.depth_info.bank_height != 0 || z.depth_info.macro_tile_aspect != 0 ||
|
||||||
@@ -176,27 +175,16 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
DepthFatal("unsupported depth register state");
|
DepthFatal("unsupported depth register state");
|
||||||
}
|
}
|
||||||
if (has_stencil) {
|
if (has_stencil) {
|
||||||
// Prospero defines Hi-Stencil as HTile-backed acceleration of the logical stencil plane.
|
|
||||||
// Keep the plane native in Vulkan while tracking HTile separately.
|
|
||||||
if (z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt) ||
|
if (z.stencil_info.format != Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt) ||
|
||||||
z.stencil_info.tile_mode_index != 0 || z.stencil_info.tile_split != 0 ||
|
!htile_stencil_compat || z.stencil_read_base_addr == 0 ||
|
||||||
!htile_stencil_compat || z.stencil_info.texture_compatible_stencil ||
|
|
||||||
z.stencil_read_base_addr == 0 ||
|
|
||||||
z.stencil_write_base_addr != z.stencil_read_base_addr ||
|
z.stencil_write_base_addr != z.stencil_read_base_addr ||
|
||||||
(z.stencil_read_base_addr & 0xffffu) != 0 || z.depth_view.stencil_write_disable) {
|
(z.stencil_read_base_addr & 0xffffu) != 0 || z.depth_view.stencil_write_disable) {
|
||||||
DepthFatal("unsupported stencil attachment state");
|
DepthFatal("unsupported stencil attachment state");
|
||||||
}
|
}
|
||||||
if (!z.stencil_info.tile_stencil_disable) {
|
|
||||||
static std::atomic_bool logged = false;
|
|
||||||
if (!logged.load(std::memory_order_relaxed) &&
|
|
||||||
!logged.exchange(true, std::memory_order_relaxed)) {
|
|
||||||
LOGF("DepthTarget: compatibility: using native stencil with PS5 HTILE "
|
|
||||||
"acceleration\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (z.stencil_read_base_addr != 0 || z.stencil_write_base_addr != 0 ||
|
} else if (z.stencil_read_base_addr != 0 || z.stencil_write_base_addr != 0 ||
|
||||||
z.stencil_info.tile_mode_index != 0 || z.stencil_info.tile_split != 0 ||
|
!htile_stencil_compat ||
|
||||||
!htile_stencil_compat || z.stencil_info.texture_compatible_stencil) {
|
z.stencil_info.texture_compatibility !=
|
||||||
|
Prospero::TextureCompatibleStencil::kDisable) {
|
||||||
DepthFatal("stencil state without an active stencil attachment");
|
DepthFatal("stencil state without an active stencil attachment");
|
||||||
}
|
}
|
||||||
if (has_htile) {
|
if (has_htile) {
|
||||||
@@ -271,16 +259,16 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
(has_htile && htile_backing_size > TRACKER_ADDRESS_SIZE - z.htile_data_base_addr)) {
|
(has_htile && htile_backing_size > TRACKER_ADDRESS_SIZE - z.htile_data_base_addr)) {
|
||||||
DepthFatal("layered depth backing range is invalid");
|
DepthFatal("layered depth backing range is invalid");
|
||||||
}
|
}
|
||||||
r.htile = has_htile;
|
r.htile = has_htile;
|
||||||
r.width = width;
|
r.width = width;
|
||||||
r.height = height;
|
r.height = height;
|
||||||
r.samples = samples;
|
r.samples = samples;
|
||||||
r.depth_buffer_size = depth_backing_size;
|
r.depth_buffer_size = depth_backing_size;
|
||||||
r.depth_buffer_vaddr = z.z_read_base_addr;
|
r.depth_buffer_vaddr = z.z_read_base_addr;
|
||||||
r.stencil_buffer_size = has_stencil ? stencil_backing_size : 0;
|
r.stencil_buffer_size = has_stencil ? stencil_backing_size : 0;
|
||||||
r.stencil_buffer_vaddr = has_stencil ? z.stencil_read_base_addr : 0;
|
r.stencil_buffer_vaddr = has_stencil ? z.stencil_read_base_addr : 0;
|
||||||
r.htile_buffer_size = has_htile ? htile_backing_size : 0;
|
r.htile_buffer_size = has_htile ? htile_backing_size : 0;
|
||||||
r.htile_buffer_vaddr = has_htile ? z.htile_data_base_addr : 0;
|
r.htile_buffer_vaddr = has_htile ? z.htile_data_base_addr : 0;
|
||||||
r.depth_clear_enable = rc.depth_clear_enable;
|
r.depth_clear_enable = rc.depth_clear_enable;
|
||||||
r.depth_meta_clear_enable = false;
|
r.depth_meta_clear_enable = false;
|
||||||
r.depth_load_clear_enable = r.depth_clear_enable;
|
r.depth_load_clear_enable = r.depth_clear_enable;
|
||||||
@@ -334,13 +322,13 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
r.size[1] = r.stencil_buffer_size;
|
r.size[1] = r.stencil_buffer_size;
|
||||||
}
|
}
|
||||||
TextureCache::ImageDesc desc {};
|
TextureCache::ImageDesc desc {};
|
||||||
desc.type = TextureCache::BindingType::DepthTarget;
|
desc.type = TextureCache::BindingType::DepthTarget;
|
||||||
desc.info.data = {r.depth_buffer_vaddr, r.depth_buffer_size};
|
desc.info.data = {r.depth_buffer_vaddr, r.depth_buffer_size};
|
||||||
desc.info.stencil = {r.stencil_buffer_vaddr, r.stencil_buffer_size};
|
desc.info.stencil = {r.stencil_buffer_vaddr, r.stencil_buffer_size};
|
||||||
desc.info.pixel_format = r.format;
|
desc.info.pixel_format = r.format;
|
||||||
desc.info.guest_format = guest_format;
|
desc.info.guest_format = guest_format;
|
||||||
desc.info.type = Prospero::ImageType::kColor2D;
|
desc.info.type = Prospero::ImageType::kColor2D;
|
||||||
desc.info.extent = {width, height, 1};
|
desc.info.extent = {width, height, 1};
|
||||||
desc.info.resources = {1, view.image_layers};
|
desc.info.resources = {1, view.image_layers};
|
||||||
desc.info.pitch = pitch;
|
desc.info.pitch = pitch;
|
||||||
desc.info.bytes_per_block = bytes;
|
desc.info.bytes_per_block = bytes;
|
||||||
@@ -350,20 +338,20 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
|
|||||||
desc.info.metadata.range = {r.htile_buffer_vaddr, r.htile_buffer_size};
|
desc.info.metadata.range = {r.htile_buffer_vaddr, r.htile_buffer_size};
|
||||||
desc.info.metadata.kind = has_htile ? ImageMetadataKind::Htile : ImageMetadataKind::None;
|
desc.info.metadata.kind = has_htile ? ImageMetadataKind::Htile : ImageMetadataKind::None;
|
||||||
desc.info.metadata.stencil_compressed =
|
desc.info.metadata.stencil_compressed =
|
||||||
has_stencil && has_htile && !z.stencil_info.tile_stencil_disable;
|
has_stencil && has_htile && !z.stencil_info.htile_stencil_disabled;
|
||||||
desc.view_info.format = r.format;
|
desc.view_info.format = r.format;
|
||||||
desc.view_info.type =
|
desc.view_info.type =
|
||||||
view.layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray;
|
view.layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray;
|
||||||
desc.view_info.aspect = ImageViewOps::DepthAspectMask(r.format);
|
desc.view_info.aspect = ImageViewOps::DepthAspectMask(r.format);
|
||||||
desc.view_info.base_level = 0;
|
desc.view_info.base_level = 0;
|
||||||
desc.view_info.level_count = 1;
|
desc.view_info.level_count = 1;
|
||||||
desc.view_info.base_layer = view.base_layer;
|
desc.view_info.base_layer = view.base_layer;
|
||||||
desc.view_info.layer_count = view.layer_count;
|
desc.view_info.layer_count = view.layer_count;
|
||||||
desc.view_info.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
desc.view_info.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||||
r.desc = std::move(desc);
|
r.desc = std::move(desc);
|
||||||
auto& cache = m_context.GetTextureCache();
|
auto& cache = m_context.GetTextureCache();
|
||||||
r.image_id = cache.FindImage(r.desc);
|
r.image_id = cache.FindImage(r.desc);
|
||||||
r.image_view = nullptr;
|
r.image_view = nullptr;
|
||||||
BindRenderTarget(r.image_id);
|
BindRenderTarget(r.image_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +360,7 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto available = ImageViewOps::DepthAspectMask(format);
|
const auto available = ImageViewOps::DepthAspectMask(format);
|
||||||
vk::ImageAspectFlags writes {};
|
vk::ImageAspectFlags writes {};
|
||||||
if ((available & vk::ImageAspectFlagBits::eDepth) &&
|
if ((available & vk::ImageAspectFlagBits::eDepth) &&
|
||||||
(depth_load_clear_enable || (depth_test_enable && depth_write_enable))) {
|
(depth_load_clear_enable || (depth_test_enable && depth_write_enable))) {
|
||||||
@@ -415,9 +403,8 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const {
|
|||||||
(can_pass && depth_fail && state.depthFailOp != vk::StencilOp::eKeep);
|
(can_pass && depth_fail && state.depthFailOp != vk::StencilOp::eKeep);
|
||||||
};
|
};
|
||||||
if (stencil_clear_enable ||
|
if (stencil_clear_enable ||
|
||||||
(stencil_test_enable &&
|
(stencil_test_enable && (face_writes(stencil_static_front, stencil_dynamic_front) ||
|
||||||
(face_writes(stencil_static_front, stencil_dynamic_front) ||
|
face_writes(stencil_static_back, stencil_dynamic_back)))) {
|
||||||
face_writes(stencil_static_back, stencil_dynamic_back)))) {
|
|
||||||
writes |= vk::ImageAspectFlagBits::eStencil;
|
writes |= vk::ImageAspectFlagBits::eStencil;
|
||||||
}
|
}
|
||||||
return writes;
|
return writes;
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ namespace Libs::Graphics {
|
|||||||
class RenderCommandBuffer;
|
class RenderCommandBuffer;
|
||||||
|
|
||||||
inline constexpr bool depth_htile_stencil_acceleration_compatible(bool has_stencil, bool has_htile,
|
inline constexpr bool depth_htile_stencil_acceleration_compatible(bool has_stencil, bool has_htile,
|
||||||
bool acceleration_disabled) {
|
bool htile_stencil_disabled) {
|
||||||
return acceleration_disabled || (has_stencil && has_htile);
|
return htile_stencil_disabled || (has_stencil && has_htile);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RenderDepthInfo {
|
struct RenderDepthInfo {
|
||||||
TextureCache::ImageDesc desc;
|
TextureCache::ImageDesc desc;
|
||||||
vk::Format format = vk::Format::eUndefined;
|
vk::Format format = vk::Format::eUndefined;
|
||||||
uint32_t width = 0;
|
uint32_t width = 0;
|
||||||
uint32_t height = 0;
|
uint32_t height = 0;
|
||||||
@@ -65,11 +65,11 @@ inline bool depth_attachment_read_only(const RenderDepthInfo& depth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline vk::ImageLayout depth_attachment_layout(const RenderDepthInfo& depth) {
|
inline vk::ImageLayout depth_attachment_layout(const RenderDepthInfo& depth) {
|
||||||
const auto available = ImageViewOps::DepthAspectMask(depth.format);
|
const auto available = ImageViewOps::DepthAspectMask(depth.format);
|
||||||
const auto writes = depth.AttachmentWriteAspects();
|
const auto writes = depth.AttachmentWriteAspects();
|
||||||
const bool has_depth = static_cast<bool>(available & vk::ImageAspectFlagBits::eDepth);
|
const bool has_depth = static_cast<bool>(available & vk::ImageAspectFlagBits::eDepth);
|
||||||
const bool has_stencil = static_cast<bool>(available & vk::ImageAspectFlagBits::eStencil);
|
const bool has_stencil = static_cast<bool>(available & vk::ImageAspectFlagBits::eStencil);
|
||||||
const bool depth_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eDepth);
|
const bool depth_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eDepth);
|
||||||
const bool stencil_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eStencil);
|
const bool stencil_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eStencil);
|
||||||
if (!has_stencil) {
|
if (!has_stencil) {
|
||||||
return depth_write ? vk::ImageLayout::eDepthAttachmentOptimal
|
return depth_write ? vk::ImageLayout::eDepthAttachmentOptimal
|
||||||
|
|||||||
@@ -73,11 +73,12 @@ static Prospero::ImageType TextureBaseType(Prospero::ImageType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferView NativeStorageBuffer(RenderContext& context,
|
static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& command_buffer,
|
||||||
CommandBuffer& command_buffer,
|
|
||||||
const ShaderBufferResource& descriptor,
|
const ShaderBufferResource& descriptor,
|
||||||
const ShaderRecompiler::IR::BufferResource& resource) {
|
const ShaderRecompiler::IR::BufferResource& resource,
|
||||||
|
uint32_t& buffer_offset) {
|
||||||
BufferView result;
|
BufferView result;
|
||||||
|
buffer_offset = 0;
|
||||||
|
|
||||||
const auto address = descriptor.Base48();
|
const auto address = descriptor.Base48();
|
||||||
const auto stride = descriptor.Stride();
|
const auto stride = descriptor.Stride();
|
||||||
@@ -93,25 +94,27 @@ static BufferView NativeStorageBuffer(RenderContext&
|
|||||||
const auto& graphics = context.GetGraphics();
|
const auto& graphics = context.GetGraphics();
|
||||||
const auto alignment = graphics.StorageMinAlignment();
|
const auto alignment = graphics.StorageMinAlignment();
|
||||||
if (alignment == 0 ||
|
if (alignment == 0 ||
|
||||||
size > graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange ||
|
size > graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange) {
|
||||||
BufferCache::CACHING_PAGE_SIZE % alignment != 0) {
|
|
||||||
EXIT("storage buffer range or device alignment is unsupported\n");
|
EXIT("storage buffer range or device alignment is unsupported\n");
|
||||||
}
|
}
|
||||||
auto binding = context.GetBufferCache().ObtainBuffer(
|
auto binding = context.GetBufferCache().ObtainBuffer(
|
||||||
command_buffer, address, size, resource.written, resource.read, resource.formatted);
|
command_buffer, address, size, resource.written, resource.read, resource.formatted);
|
||||||
if (binding.offset % alignment != 0) {
|
const auto aligned_offset = binding.offset - binding.offset % alignment;
|
||||||
EXIT("storage buffer binding is not device-aligned\n");
|
const auto adjustment = binding.offset - aligned_offset;
|
||||||
|
const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange;
|
||||||
|
if (adjustment % sizeof(uint32_t) != 0 || adjustment >= 256 || size > max_range - adjustment) {
|
||||||
|
EXIT("storage buffer offset adjustment is unsupported\n");
|
||||||
}
|
}
|
||||||
|
buffer_offset = static_cast<uint32_t>(adjustment);
|
||||||
result.owner = std::move(binding.owner);
|
result.owner = std::move(binding.owner);
|
||||||
result.buffer = binding.buffer;
|
result.buffer = binding.buffer;
|
||||||
result.offset = binding.offset;
|
result.offset = aligned_offset;
|
||||||
result.range = static_cast<vk::DeviceSize>(size);
|
result.range = static_cast<vk::DeviceSize>(size + adjustment);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferView
|
static BufferView
|
||||||
NativeAddressBuffer(RenderContext& context,
|
NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
|
||||||
CommandBuffer& command_buffer,
|
|
||||||
const ShaderRecompiler::IR::AddressResource& resource,
|
const ShaderRecompiler::IR::AddressResource& resource,
|
||||||
const ShaderRecompiler::IR::ResourceSnapshot::Address& address) {
|
const ShaderRecompiler::IR::ResourceSnapshot::Address& address) {
|
||||||
BufferView result;
|
BufferView result;
|
||||||
@@ -122,11 +125,11 @@ NativeAddressBuffer(RenderContext& conte
|
|||||||
if (resource.written) {
|
if (resource.written) {
|
||||||
EXIT("writable address resources are unsupported\n");
|
EXIT("writable address resources are unsupported\n");
|
||||||
}
|
}
|
||||||
const auto limit = resource.kind == ShaderRecompiler::IR::ResourceKind::Flat
|
const auto limit =
|
||||||
? ShaderRecompiler::IR::FlatAddressWindowSize
|
resource.kind == ShaderRecompiler::IR::ResourceKind::Flat
|
||||||
: static_cast<uint64_t>(context.GetGraphics()
|
? ShaderRecompiler::IR::FlatAddressWindowSize
|
||||||
.GetPhysicalDeviceProperties()
|
: static_cast<uint64_t>(
|
||||||
.limits.maxStorageBufferRange);
|
context.GetGraphics().GetPhysicalDeviceProperties().limits.maxStorageBufferRange);
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
const auto access = HostMemoryAccess::Mapped;
|
const auto access = HostMemoryAccess::Mapped;
|
||||||
if (!HostMemoryQueryRange(address.binding_base, limit, access, size)) {
|
if (!HostMemoryQueryRange(address.binding_base, limit, access, size)) {
|
||||||
@@ -291,7 +294,7 @@ static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::Imag
|
|||||||
descriptor.BaseArray5() == 0;
|
descriptor.BaseArray5() == 0;
|
||||||
TileBlockLayout depth_block {};
|
TileBlockLayout depth_block {};
|
||||||
const auto depth_bpe = Prospero::RenderTargetBytesPerElement(descriptor.Format());
|
const auto depth_bpe = Prospero::RenderTargetBytesPerElement(descriptor.Format());
|
||||||
const bool supported_depth_tile =
|
const bool supported_depth_tile =
|
||||||
tile == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && !resource.read &&
|
tile == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && !resource.read &&
|
||||||
!Prospero::IsFmaskTextureFormat(descriptor.Format()) && (is_2d || is_2d_array) &&
|
!Prospero::IsFmaskTextureFormat(descriptor.Format()) && (is_2d || is_2d_array) &&
|
||||||
TileGetBlockLayout(TileBlockFamily::Depth64KB, depth_bpe, depth_block);
|
TileGetBlockLayout(TileBlockFamily::Depth64KB, depth_bpe, depth_block);
|
||||||
@@ -301,9 +304,9 @@ static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::Imag
|
|||||||
const bool supported_tile = tile == Prospero::GpuEnumValue(Prospero::TileMode::kLinear) ||
|
const bool supported_tile = tile == Prospero::GpuEnumValue(Prospero::TileMode::kLinear) ||
|
||||||
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
|
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
|
||||||
supported_depth_tile || supported_standard_tile;
|
supported_depth_tile || supported_standard_tile;
|
||||||
const bool supported_swizzle = IsValidImageSwizzle(descriptor.DstSelXYZW()) &&
|
const bool supported_swizzle =
|
||||||
(descriptor.DstSelXYZW() == DstSel(4, 5, 6, 7) ||
|
IsValidImageSwizzle(descriptor.DstSelXYZW()) &&
|
||||||
!resource.read);
|
(descriptor.DstSelXYZW() == DstSel(4, 5, 6, 7) || !resource.read);
|
||||||
const bool supported_mip_view = descriptor.BaseLevel() == 0 || is_2d;
|
const bool supported_mip_view = descriptor.BaseLevel() == 0 || is_2d;
|
||||||
return (is_2d || is_2d_array || is_3d) && supported_tile && supported_mip_view &&
|
return (is_2d || is_2d_array || is_3d) && supported_tile && supported_mip_view &&
|
||||||
descriptor.BaseLevel() == descriptor.LastLevel() &&
|
descriptor.BaseLevel() == descriptor.LastLevel() &&
|
||||||
@@ -321,7 +324,7 @@ static bool IsSupportedStorageTextureEncoding(const ShaderTextureResource& descr
|
|||||||
(static_cast<uint32_t>(descriptor.LastLevel()) << 16u) |
|
(static_cast<uint32_t>(descriptor.LastLevel()) << 16u) |
|
||||||
(static_cast<uint32_t>(descriptor.TileMode()) << 20u) |
|
(static_cast<uint32_t>(descriptor.TileMode()) << 20u) |
|
||||||
(static_cast<uint32_t>(descriptor.Type()) << 28u);
|
(static_cast<uint32_t>(descriptor.Type()) << 28u);
|
||||||
const uint32_t expected_field4 =
|
const uint32_t expected_field4 =
|
||||||
descriptor.Depth() | (static_cast<uint32_t>(descriptor.BaseArray5()) << 16u);
|
descriptor.Depth() | (static_cast<uint32_t>(descriptor.BaseArray5()) << 16u);
|
||||||
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 &&
|
||||||
@@ -354,8 +357,8 @@ void ValidateStorageTexture(const ShaderRecompiler::IR::ImageResource& resource,
|
|||||||
resource.atomic, resource.depth_compare, descriptor.BaseLevel(), descriptor.LastLevel(),
|
resource.atomic, resource.depth_compare, descriptor.BaseLevel(), descriptor.LastLevel(),
|
||||||
descriptor.MaxMip(), descriptor.MinLod(), descriptor.BaseArray5(), descriptor.BCSwizzle(),
|
descriptor.MaxMip(), descriptor.MinLod(), descriptor.BaseArray5(), descriptor.BCSwizzle(),
|
||||||
descriptor.MsaaDepth(), Prospero::RenderTargetBytesPerElement(format),
|
descriptor.MsaaDepth(), Prospero::RenderTargetBytesPerElement(format),
|
||||||
IsValidImageSwizzle(descriptor.DstSelXYZW()),
|
IsValidImageSwizzle(descriptor.DstSelXYZW()), descriptor.Base40(), size,
|
||||||
descriptor.Base40(), size, static_cast<uint32_t>(descriptor.Width5()) + 1u,
|
static_cast<uint32_t>(descriptor.Width5()) + 1u,
|
||||||
static_cast<uint32_t>(descriptor.Height5()) + 1u,
|
static_cast<uint32_t>(descriptor.Height5()) + 1u,
|
||||||
static_cast<uint32_t>(descriptor.Depth()) + 1u, descriptor.Type(), format,
|
static_cast<uint32_t>(descriptor.Depth()) + 1u, descriptor.Type(), format,
|
||||||
descriptor.TileMode(), descriptor.DstSelXYZW(), resource.read, resource.written,
|
descriptor.TileMode(), descriptor.DstSelXYZW(), resource.read, resource.written,
|
||||||
@@ -371,17 +374,15 @@ struct NullImageSpec {
|
|||||||
static NullImageSpec NullTextureSpec(const ShaderRecompiler::IR::ImageResource& resource) {
|
static NullImageSpec NullTextureSpec(const ShaderRecompiler::IR::ImageResource& resource) {
|
||||||
const bool uint_image = resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint ||
|
const bool uint_image = resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint ||
|
||||||
resource.kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint;
|
resource.kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint;
|
||||||
return uint_image
|
return uint_image ? NullImageSpec {vk::Format::eR32Uint,
|
||||||
? NullImageSpec {vk::Format::eR32Uint,
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt)}
|
||||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt)}
|
: NullImageSpec {vk::Format::eR32Sfloat,
|
||||||
: NullImageSpec {vk::Format::eR32Sfloat,
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float)};
|
||||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TextureCache::ImageDesc
|
static TextureCache::ImageDesc NullTextureDesc(const ShaderRecompiler::IR::ImageResource& resource,
|
||||||
NullTextureDesc(const ShaderRecompiler::IR::ImageResource& resource,
|
TextureCache::BindingType binding) {
|
||||||
TextureCache::BindingType binding) {
|
const auto spec = NullTextureSpec(resource);
|
||||||
const auto spec = NullTextureSpec(resource);
|
|
||||||
TextureCache::ImageDesc desc {};
|
TextureCache::ImageDesc desc {};
|
||||||
desc.info.pixel_format = spec.format;
|
desc.info.pixel_format = spec.format;
|
||||||
desc.info.guest_format = spec.guest_format;
|
desc.info.guest_format = spec.guest_format;
|
||||||
@@ -394,9 +395,9 @@ NullTextureDesc(const ShaderRecompiler::IR::ImageResource& resource,
|
|||||||
desc.view_info.format = desc.info.pixel_format;
|
desc.view_info.format = desc.info.pixel_format;
|
||||||
desc.view_info.type = vk::ImageViewType::e2D;
|
desc.view_info.type = vk::ImageViewType::e2D;
|
||||||
desc.view_info.aspect = vk::ImageAspectFlagBits::eColor;
|
desc.view_info.aspect = vk::ImageAspectFlagBits::eColor;
|
||||||
desc.view_info.usage =
|
desc.view_info.usage = binding == TextureCache::BindingType::Storage
|
||||||
binding == TextureCache::BindingType::Storage ? vk::ImageUsageFlagBits::eStorage
|
? vk::ImageUsageFlagBits::eStorage
|
||||||
: vk::ImageUsageFlagBits::eSampled;
|
: vk::ImageUsageFlagBits::eSampled;
|
||||||
desc.type = binding;
|
desc.type = binding;
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
@@ -446,8 +447,7 @@ static void PopulateTextureMipLayout(ImageInfo& info) {
|
|||||||
|
|
||||||
static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource,
|
static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource,
|
||||||
const ShaderTextureResource& descriptor, vk::Format format,
|
const ShaderTextureResource& descriptor, vk::Format format,
|
||||||
bool storage, uint32_t view_levels,
|
bool storage, uint32_t view_levels, uint32_t image_layers) {
|
||||||
uint32_t image_layers) {
|
|
||||||
ImageViewInfo view {};
|
ImageViewInfo view {};
|
||||||
view.format = format;
|
view.format = format;
|
||||||
view.aspect = vk::ImageAspectFlagBits::eColor;
|
view.aspect = vk::ImageAspectFlagBits::eColor;
|
||||||
@@ -480,8 +480,8 @@ static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource&
|
|||||||
}
|
}
|
||||||
|
|
||||||
DescriptorCache::TextureBinding
|
DescriptorCache::TextureBinding
|
||||||
RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resource,
|
RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resource,
|
||||||
const ShaderRecompiler::IR::DescriptorValue& value) {
|
const ShaderRecompiler::IR::DescriptorValue& value) {
|
||||||
ShaderTextureResource descriptor;
|
ShaderTextureResource descriptor;
|
||||||
CopyNativeDescriptor(value, descriptor.fields);
|
CopyNativeDescriptor(value, descriptor.fields);
|
||||||
const bool storage = resource.written;
|
const bool storage = resource.written;
|
||||||
@@ -491,9 +491,9 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
|
|
||||||
auto& texture_cache = m_context.GetTextureCache();
|
auto& texture_cache = m_context.GetTextureCache();
|
||||||
if (descriptor.IsNull()) {
|
if (descriptor.IsNull()) {
|
||||||
auto desc = NullTextureDesc(resource, storage ? TextureCache::BindingType::Storage
|
auto desc = NullTextureDesc(resource, storage ? TextureCache::BindingType::Storage
|
||||||
: TextureCache::BindingType::Texture);
|
: TextureCache::BindingType::Texture);
|
||||||
const auto id = texture_cache.FindImage(desc);
|
const auto id = texture_cache.FindImage(desc);
|
||||||
return {id, nullptr, std::move(desc)};
|
return {id, nullptr, std::move(desc)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,12 +504,10 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
const auto last_level = descriptor.LastLevel();
|
const auto last_level = descriptor.LastLevel();
|
||||||
const auto type = TextureType(descriptor);
|
const auto type = TextureType(descriptor);
|
||||||
const bool multisampled =
|
const bool multisampled =
|
||||||
type == Prospero::ImageType::kColor2DMsaa ||
|
type == Prospero::ImageType::kColor2DMsaa || type == Prospero::ImageType::kColor2DMsaaArray;
|
||||||
type == Prospero::ImageType::kColor2DMsaaArray;
|
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
|
||||||
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
|
const auto tile = descriptor.TileMode();
|
||||||
const auto tile = descriptor.TileMode();
|
const bool msaa_tile = tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
|
||||||
const bool msaa_tile =
|
|
||||||
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
|
|
||||||
const bool msaa_array = type == Prospero::ImageType::kColor2DMsaaArray;
|
const bool msaa_array = type == Prospero::ImageType::kColor2DMsaaArray;
|
||||||
if ((!multisampled && (base_level > last_level || last_level >= levels)) ||
|
if ((!multisampled && (base_level > last_level || last_level >= levels)) ||
|
||||||
(multisampled &&
|
(multisampled &&
|
||||||
@@ -519,7 +517,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
EXIT("unsupported texture mip view: base=%u last=%u levels=%u\n", base_level, last_level,
|
EXIT("unsupported texture mip view: base=%u last=%u levels=%u\n", base_level, last_level,
|
||||||
levels);
|
levels);
|
||||||
}
|
}
|
||||||
const auto samples = multisampled ? 1u << last_level : 1u;
|
const auto samples = multisampled ? 1u << last_level : 1u;
|
||||||
const auto view_levels =
|
const auto view_levels =
|
||||||
multisampled ? 1u : static_cast<uint32_t>(last_level - base_level) + 1u;
|
multisampled ? 1u : static_cast<uint32_t>(last_level - base_level) + 1u;
|
||||||
const auto depth = static_cast<uint32_t>(descriptor.Depth()) + 1u;
|
const auto depth = static_cast<uint32_t>(descriptor.Depth()) + 1u;
|
||||||
@@ -535,26 +533,25 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
static_cast<uint32_t>(resource.kind), format, address);
|
static_cast<uint32_t>(resource.kind), format, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool volume = type == Prospero::ImageType::kColor3D;
|
const bool volume = type == Prospero::ImageType::kColor3D;
|
||||||
const bool layered = type == Prospero::ImageType::kColor1DArray ||
|
const bool layered = type == Prospero::ImageType::kColor1DArray ||
|
||||||
type == Prospero::ImageType::kColor2DArray ||
|
type == Prospero::ImageType::kColor2DArray ||
|
||||||
type == Prospero::ImageType::kColor2DMsaaArray;
|
type == Prospero::ImageType::kColor2DMsaaArray;
|
||||||
const auto image_layers = layered ? depth : 1u;
|
const auto image_layers = layered ? depth : 1u;
|
||||||
uint32_t pitch = 0;
|
uint32_t pitch = 0;
|
||||||
TileSizeAlign size {};
|
TileSizeAlign size {};
|
||||||
if (multisampled) {
|
if (multisampled) {
|
||||||
const auto bytes = Prospero::NumBytesPerElement(format);
|
const auto bytes = Prospero::NumBytesPerElement(format);
|
||||||
pitch = TileGetRenderTargetPitch(width, bytes, last_level);
|
pitch = TileGetRenderTargetPitch(width, bytes, last_level);
|
||||||
if (pitch == 0 ||
|
if (pitch == 0 || !TileGetRenderTargetSize(width, height, pitch, bytes, size, last_level) ||
|
||||||
!TileGetRenderTargetSize(width, height, pitch, bytes, size, last_level) ||
|
|
||||||
size.size > UINT32_MAX / image_layers) {
|
size.size > UINT32_MAX / image_layers) {
|
||||||
EXIT("unsupported multisample texture layout\n");
|
EXIT("unsupported multisample texture layout\n");
|
||||||
}
|
}
|
||||||
size.size *= image_layers;
|
size.size *= image_layers;
|
||||||
} else {
|
} else {
|
||||||
pitch = TileGetTexturePitch(format, width, levels, tile);
|
pitch = TileGetTexturePitch(format, width, levels, tile);
|
||||||
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, pitch,
|
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, pitch, levels,
|
||||||
levels, tile, volume, size);
|
tile, volume, size);
|
||||||
}
|
}
|
||||||
EXIT_NOT_IMPLEMENTED(size.size == 0 || size.align == 0 ||
|
EXIT_NOT_IMPLEMENTED(size.size == 0 || size.align == 0 ||
|
||||||
(address & (static_cast<uint64_t>(size.align) - 1u)) != 0);
|
(address & (static_cast<uint64_t>(size.align) - 1u)) != 0);
|
||||||
@@ -564,8 +561,8 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
resource.written);
|
resource.written);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto pixel_format = TextureGetFormat(format);
|
const auto pixel_format = TextureGetFormat(format);
|
||||||
const auto block_bytes = Prospero::BlockCompressedBytesPerBlock(format);
|
const auto block_bytes = Prospero::BlockCompressedBytesPerBlock(format);
|
||||||
TextureCache::ImageDesc desc {};
|
TextureCache::ImageDesc desc {};
|
||||||
desc.info.data = {address, size.size};
|
desc.info.data = {address, size.size};
|
||||||
desc.info.pixel_format = pixel_format;
|
desc.info.pixel_format = pixel_format;
|
||||||
@@ -585,11 +582,10 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
}
|
}
|
||||||
desc.view_info = TextureViewInfo(resource, descriptor, pixel_format, storage, view_levels,
|
desc.view_info = TextureViewInfo(resource, descriptor, pixel_format, storage, view_levels,
|
||||||
desc.info.resources.layers);
|
desc.info.resources.layers);
|
||||||
desc.type = storage ? TextureCache::BindingType::Storage
|
desc.type = storage ? TextureCache::BindingType::Storage : TextureCache::BindingType::Texture;
|
||||||
: TextureCache::BindingType::Texture;
|
|
||||||
|
|
||||||
auto id = texture_cache.FindImage(desc);
|
auto id = texture_cache.FindImage(desc);
|
||||||
auto* image = &texture_cache.GetImage(id);
|
auto* image = &texture_cache.GetImage(id);
|
||||||
const bool stencil_association = static_cast<bool>(image->depth_id);
|
const bool stencil_association = static_cast<bool>(image->depth_id);
|
||||||
if (stencil_association) {
|
if (stencil_association) {
|
||||||
id = image->depth_id;
|
id = image->depth_id;
|
||||||
@@ -610,7 +606,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
|
|||||||
return {id, nullptr, std::move(desc)};
|
return {id, nullptr, std::move(desc)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static vk::Sampler NativeSampler(RenderContext& context,
|
static vk::Sampler NativeSampler(RenderContext& context,
|
||||||
const ShaderRecompiler::IR::Program& program, uint32_t index,
|
const ShaderRecompiler::IR::Program& program, uint32_t index,
|
||||||
const ShaderRecompiler::IR::DescriptorValue& value) {
|
const ShaderRecompiler::IR::DescriptorValue& value) {
|
||||||
ShaderSamplerResource descriptor;
|
ShaderSamplerResource descriptor;
|
||||||
@@ -631,8 +627,7 @@ static BufferView NativeUpload(RenderContext& context, CommandBuffer& command_bu
|
|||||||
std::span<const uint32_t> data) {
|
std::span<const uint32_t> data) {
|
||||||
EXIT_IF(data.empty());
|
EXIT_IF(data.empty());
|
||||||
EXIT_IF(command_buffer.IsInvalid() || command_buffer.IsExecute());
|
EXIT_IF(command_buffer.IsInvalid() || command_buffer.IsExecute());
|
||||||
auto binding =
|
auto binding = context.GetBufferCache().UploadTransient(data.data(), data.size_bytes(), 256);
|
||||||
context.GetBufferCache().UploadTransient(data.data(), data.size_bytes(), 256);
|
|
||||||
return {.owner = std::move(binding.owner),
|
return {.owner = std::move(binding.owner),
|
||||||
.buffer = binding.buffer,
|
.buffer = binding.buffer,
|
||||||
.offset = binding.offset,
|
.offset = binding.offset,
|
||||||
@@ -660,8 +655,8 @@ void RenderExecutor::BindImage(ImageId id, bool storage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderExecutor::BindRenderTarget(ImageId id) {
|
void RenderExecutor::BindRenderTarget(ImageId id) {
|
||||||
auto& image = m_context.GetTextureCache().GetImage(id);
|
auto& image = m_context.GetTextureCache().GetImage(id);
|
||||||
image.binding.is_target = true;
|
image.binding.is_target = true;
|
||||||
TrackImageBinding(id);
|
TrackImageBinding(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,9 +667,10 @@ void RenderExecutor::ResetBindings() {
|
|||||||
m_bound_images.clear();
|
m_bound_images.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptorCache::PreparedBindings
|
DescriptorCache::PreparedBindings RenderExecutor::PrepareBindings(CommandBuffer& buffer,
|
||||||
RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime& runtime,
|
const ShaderStageRuntime& runtime,
|
||||||
vk::ShaderStageFlags shader_stage, DescriptorCache::Stage stage) {
|
vk::ShaderStageFlags shader_stage,
|
||||||
|
DescriptorCache::Stage stage) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
EXIT_IF(!runtime);
|
EXIT_IF(!runtime);
|
||||||
const auto& program = *runtime.program;
|
const auto& program = *runtime.program;
|
||||||
@@ -691,12 +687,6 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
|
|||||||
prepared.stage = stage;
|
prepared.stage = stage;
|
||||||
auto& descriptors = prepared.resources;
|
auto& descriptors = prepared.resources;
|
||||||
descriptors.buffers.reserve(program.info.buffers.size());
|
descriptors.buffers.reserve(program.info.buffers.size());
|
||||||
for (uint32_t i = 0; i < program.info.buffers.size(); i++) {
|
|
||||||
ShaderBufferResource descriptor;
|
|
||||||
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
|
|
||||||
descriptors.buffers.push_back(
|
|
||||||
NativeStorageBuffer(m_context, buffer, descriptor, program.info.buffers[i]));
|
|
||||||
}
|
|
||||||
descriptors.images.reserve(program.info.images.size());
|
descriptors.images.reserve(program.info.images.size());
|
||||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||||
auto binding = ResolveTexture(program.info.images[i], snapshot.images[i]);
|
auto binding = ResolveTexture(program.info.images[i], snapshot.images[i]);
|
||||||
@@ -705,13 +695,7 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
|
|||||||
}
|
}
|
||||||
descriptors.samplers.reserve(program.info.samplers.size());
|
descriptors.samplers.reserve(program.info.samplers.size());
|
||||||
for (uint32_t i = 0; i < program.info.samplers.size(); i++) {
|
for (uint32_t i = 0; i < program.info.samplers.size(); i++) {
|
||||||
descriptors.samplers.push_back(
|
descriptors.samplers.push_back(NativeSampler(m_context, program, i, snapshot.samplers[i]));
|
||||||
NativeSampler(m_context, program, i, snapshot.samplers[i]));
|
|
||||||
}
|
|
||||||
descriptors.addresses.reserve(program.info.addresses.size());
|
|
||||||
for (uint32_t i = 0; i < program.info.addresses.size(); i++) {
|
|
||||||
descriptors.addresses.push_back(NativeAddressBuffer(
|
|
||||||
m_context, buffer, program.info.addresses[i], snapshot.addresses[i]));
|
|
||||||
}
|
}
|
||||||
if (ShaderRecompiler::IR::FindBinding(
|
if (ShaderRecompiler::IR::FindBinding(
|
||||||
program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::FlattenedSrt) !=
|
program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::FlattenedSrt) !=
|
||||||
@@ -719,10 +703,11 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
|
|||||||
prepared.flattened_srt.assign(snapshot.flattened_srt.begin(), snapshot.flattened_srt.end());
|
prepared.flattened_srt.assign(snapshot.flattened_srt.begin(), snapshot.flattened_srt.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
prepared.user_data.reserve(program.bindings.user_data_registers.size());
|
prepared.user_data.reserve(program.bindings.ShaderDataDwords());
|
||||||
for (const auto reg: program.bindings.user_data_registers) {
|
for (const auto reg: program.bindings.user_data_registers) {
|
||||||
prepared.user_data.push_back(snapshot.user_data[reg - program.user_data_base]);
|
prepared.user_data.push_back(snapshot.user_data[reg - program.user_data_base]);
|
||||||
}
|
}
|
||||||
|
prepared.user_data.resize(program.bindings.ShaderDataDwords());
|
||||||
if (ShaderRecompiler::IR::FindBinding(
|
if (ShaderRecompiler::IR::FindBinding(
|
||||||
program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::Gds) != nullptr) {
|
program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::Gds) != nullptr) {
|
||||||
descriptors.gds.buffer = m_context.GetBufferCache().GetGdsBuffer().Handle();
|
descriptors.gds.buffer = m_context.GetBufferCache().GetGdsBuffer().Handle();
|
||||||
@@ -730,21 +715,28 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
|
|||||||
return prepared;
|
return prepared;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
|
void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
|
||||||
DescriptorCache::PreparedBindings& prepared) {
|
DescriptorCache::PreparedBindings& prepared) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
|
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
|
||||||
const auto& program = *prepared.program;
|
const auto& program = *prepared.program;
|
||||||
const auto& snapshot = *prepared.snapshot;
|
const auto& snapshot = *prepared.snapshot;
|
||||||
auto& resources = prepared.resources;
|
auto& resources = prepared.resources;
|
||||||
|
const auto& layout = program.bindings;
|
||||||
|
|
||||||
resources.buffers.clear();
|
resources.buffers.clear();
|
||||||
resources.buffers.reserve(program.info.buffers.size());
|
resources.buffers.reserve(program.info.buffers.size());
|
||||||
|
EXIT_IF(prepared.user_data.size() != layout.ShaderDataDwords());
|
||||||
|
std::fill(prepared.user_data.begin() + layout.buffer_offset_dword, prepared.user_data.end(), 0);
|
||||||
for (uint32_t i = 0; i < program.info.buffers.size(); i++) {
|
for (uint32_t i = 0; i < program.info.buffers.size(); i++) {
|
||||||
ShaderBufferResource descriptor;
|
ShaderBufferResource descriptor;
|
||||||
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
|
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
|
||||||
resources.buffers.push_back(
|
uint32_t buffer_offset = 0;
|
||||||
NativeStorageBuffer(m_context, buffer, descriptor, program.info.buffers[i]));
|
resources.buffers.push_back(NativeStorageBuffer(m_context, buffer, descriptor,
|
||||||
|
program.info.buffers[i], buffer_offset));
|
||||||
|
const auto dword = layout.buffer_offset_dword + i / 4u;
|
||||||
|
const auto shift = (i % 4u) * 8u;
|
||||||
|
prepared.user_data[dword] |= buffer_offset << shift;
|
||||||
}
|
}
|
||||||
resources.addresses.clear();
|
resources.addresses.clear();
|
||||||
resources.addresses.reserve(program.info.addresses.size());
|
resources.addresses.reserve(program.info.addresses.size());
|
||||||
@@ -754,8 +746,8 @@ void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderExecutor::RebindImages(CommandBuffer& buffer,
|
void RenderExecutor::RebindImages(CommandBuffer& buffer,
|
||||||
DescriptorCache::PreparedBindings& prepared) {
|
DescriptorCache::PreparedBindings& prepared) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
|
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
|
||||||
const auto& program = *prepared.program;
|
const auto& program = *prepared.program;
|
||||||
@@ -765,8 +757,7 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
|
|||||||
auto& texture_cache = m_context.GetTextureCache();
|
auto& texture_cache = m_context.GetTextureCache();
|
||||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||||
const auto old_image = texture_cache.ResolveOwner(images[i].image_id);
|
const auto old_image = texture_cache.ResolveOwner(images[i].image_id);
|
||||||
if (old_image == nullptr ||
|
if (old_image == nullptr || (!old_image->registered && !old_image->info.data.Empty()) ||
|
||||||
(!old_image->registered && !old_image->info.data.Empty()) ||
|
|
||||||
old_image->binding.needs_rebind) {
|
old_image->binding.needs_rebind) {
|
||||||
if (old_image != nullptr) {
|
if (old_image != nullptr) {
|
||||||
old_image->binding = {};
|
old_image->binding = {};
|
||||||
@@ -775,10 +766,10 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
|
|||||||
BindImage(images[i].image_id,
|
BindImage(images[i].image_id,
|
||||||
images[i].desc.type == TextureCache::BindingType::Storage);
|
images[i].desc.type == TextureCache::BindingType::Storage);
|
||||||
}
|
}
|
||||||
auto& binding = images[i];
|
auto& binding = images[i];
|
||||||
binding.image_view = texture_cache.FindTexture(binding.image_id, binding.desc);
|
binding.image_view = texture_cache.FindTexture(binding.image_id, binding.desc);
|
||||||
auto& image = texture_cache.GetImage(binding.image_id);
|
auto& image = texture_cache.GetImage(binding.image_id);
|
||||||
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
|
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
|
||||||
image.usage.storage |= storage;
|
image.usage.storage |= storage;
|
||||||
image.usage.texture |= !storage;
|
image.usage.texture |= !storage;
|
||||||
}
|
}
|
||||||
@@ -786,7 +777,7 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
|
|||||||
|
|
||||||
RenderExecutor::GraphicsBindings
|
RenderExecutor::GraphicsBindings
|
||||||
RenderExecutor::PrepareGraphicsBindings(CommandBuffer& buffer, const ShaderStageRuntime& vertex,
|
RenderExecutor::PrepareGraphicsBindings(CommandBuffer& buffer, const ShaderStageRuntime& vertex,
|
||||||
const ShaderStageRuntime& pixel, bool pixel_active) {
|
const ShaderStageRuntime& pixel, bool pixel_active) {
|
||||||
GraphicsBindings bindings {
|
GraphicsBindings bindings {
|
||||||
.vertex = PrepareBindings(buffer, vertex, vk::ShaderStageFlagBits::eVertex,
|
.vertex = PrepareBindings(buffer, vertex, vk::ShaderStageFlagBits::eVertex,
|
||||||
DescriptorCache::Stage::Vertex),
|
DescriptorCache::Stage::Vertex),
|
||||||
@@ -822,10 +813,10 @@ static void RetainBindings(CommandBuffer& buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
||||||
vk::PipelineBindPoint pipeline_bind_point,
|
vk::PipelineBindPoint pipeline_bind_point,
|
||||||
vk::PipelineLayout layout,
|
vk::PipelineLayout layout,
|
||||||
DescriptorCache::PreparedBindings& prepared) {
|
DescriptorCache::PreparedBindings& prepared) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
EXIT_IF(prepared.program == nullptr || prepared.stage == DescriptorCache::Stage::Unknown ||
|
EXIT_IF(prepared.program == nullptr || prepared.stage == DescriptorCache::Stage::Unknown ||
|
||||||
prepared.committed);
|
prepared.committed);
|
||||||
@@ -852,7 +843,7 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||||
auto& image = m_context.GetTextureCache().GetImage(descriptors.images[i].image_id);
|
auto& image = m_context.GetTextureCache().GetImage(descriptors.images[i].image_id);
|
||||||
auto& binding = descriptors.images[i];
|
auto& binding = descriptors.images[i];
|
||||||
const auto& view = binding.desc.view_info;
|
const auto& view = binding.desc.view_info;
|
||||||
const ImageSubresourceRange range {view.base_level, view.level_count, view.base_layer,
|
const ImageSubresourceRange range {view.base_level, view.level_count, view.base_layer,
|
||||||
@@ -860,9 +851,9 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
|||||||
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
|
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
|
||||||
if (image.info.data.Empty()) {
|
if (image.info.data.Empty()) {
|
||||||
image.Transit(vk::ImageLayout::eGeneral,
|
image.Transit(vk::ImageLayout::eGeneral,
|
||||||
storage ? vk::AccessFlagBits2::eShaderRead |
|
storage
|
||||||
vk::AccessFlagBits2::eShaderWrite
|
? vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite
|
||||||
: vk::AccessFlagBits2::eShaderRead,
|
: vk::AccessFlagBits2::eShaderRead,
|
||||||
range, vk_buffer);
|
range, vk_buffer);
|
||||||
} else if ((image.binding.force_general || image.binding.is_target) &&
|
} else if ((image.binding.force_general || image.binding.is_target) &&
|
||||||
!image.info.IsDepth()) {
|
!image.info.IsDepth()) {
|
||||||
@@ -877,7 +868,7 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
|||||||
range, vk_buffer);
|
range, vk_buffer);
|
||||||
} else {
|
} else {
|
||||||
image.Transit(image.info.IsDepth() ? vk::ImageLayout::eDepthStencilReadOnlyOptimal
|
image.Transit(image.info.IsDepth() ? vk::ImageLayout::eDepthStencilReadOnlyOptimal
|
||||||
: vk::ImageLayout::eShaderReadOnlyOptimal,
|
: vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
vk::AccessFlagBits2::eShaderRead, range, vk_buffer);
|
vk::AccessFlagBits2::eShaderRead, range, vk_buffer);
|
||||||
}
|
}
|
||||||
binding.layout = image.backing.state.layout;
|
binding.layout = image.backing.state.layout;
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
next.buffer_offset_dword = static_cast<uint32_t>(next.user_data_registers.size());
|
||||||
|
next.buffer_offset_count = static_cast<uint32_t>(program.info.buffers.size());
|
||||||
|
|
||||||
if (!program.info.buffers.empty()) {
|
if (!program.info.buffers.empty()) {
|
||||||
std::vector<uint32_t> resources(program.info.buffers.size());
|
std::vector<uint32_t> resources(program.info.buffers.size());
|
||||||
@@ -269,8 +271,8 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
|||||||
|
|
||||||
const auto available_push_dwords = (MaxPushConstantBytes - options.push_constant_offset) / 4u;
|
const auto available_push_dwords = (MaxPushConstantBytes - options.push_constant_offset) / 4u;
|
||||||
const auto push_limit = std::min(options.max_push_dwords, available_push_dwords);
|
const auto push_limit = std::min(options.max_push_dwords, available_push_dwords);
|
||||||
if (next.user_data_registers.size() <= push_limit) {
|
if (next.ShaderDataDwords() <= push_limit) {
|
||||||
next.push_constant_size = static_cast<uint32_t>(next.user_data_registers.size() * 4u);
|
next.push_constant_size = next.ShaderDataDwords() * sizeof(uint32_t);
|
||||||
} else {
|
} else {
|
||||||
AddBinding(next, DescriptorBindingKind::UserData);
|
AddBinding(next, DescriptorBindingKind::UserData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,6 +249,12 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime,
|
|||||||
auto cursor = values.begin();
|
auto cursor = values.begin();
|
||||||
next.buffers.assign(cursor, cursor + program.info.buffers.size());
|
next.buffers.assign(cursor, cursor + program.info.buffers.size());
|
||||||
cursor += program.info.buffers.size();
|
cursor += program.info.buffers.size();
|
||||||
|
for (auto& descriptor: next.buffers) {
|
||||||
|
ShaderBufferResource buffer;
|
||||||
|
if (DecodeBufferDescriptor(descriptor, buffer) && buffer.Type() != 0) {
|
||||||
|
descriptor.dwords.fill(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
next.images.assign(cursor, cursor + program.info.images.size());
|
next.images.assign(cursor, cursor + program.info.images.size());
|
||||||
cursor += program.info.images.size();
|
cursor += program.info.images.size();
|
||||||
for (auto& descriptor: next.images) {
|
for (auto& descriptor: next.images) {
|
||||||
|
|||||||
@@ -705,9 +705,15 @@ struct BindingLayout {
|
|||||||
uint32_t descriptor_set = 0;
|
uint32_t descriptor_set = 0;
|
||||||
uint32_t push_constant_offset = 0;
|
uint32_t push_constant_offset = 0;
|
||||||
uint32_t push_constant_size = 0;
|
uint32_t push_constant_size = 0;
|
||||||
|
uint32_t buffer_offset_dword = 0;
|
||||||
|
uint32_t buffer_offset_count = 0;
|
||||||
std::vector<uint32_t> user_data_registers;
|
std::vector<uint32_t> user_data_registers;
|
||||||
std::vector<DescriptorBinding> descriptors;
|
std::vector<DescriptorBinding> descriptors;
|
||||||
|
|
||||||
|
[[nodiscard]] uint32_t ShaderDataDwords() const {
|
||||||
|
return buffer_offset_dword + (buffer_offset_count + 3u) / 4u;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const BindingLayout& other) const = default;
|
bool operator==(const BindingLayout& other) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
|||||||
if (!program.srt.reads.empty()) {
|
if (!program.srt.reads.empty()) {
|
||||||
Expect(Kind::FlattenedSrt);
|
Expect(Kind::FlattenedSrt);
|
||||||
}
|
}
|
||||||
if (!program.bindings.user_data_registers.empty() && program.bindings.push_constant_size == 0) {
|
if (program.bindings.ShaderDataDwords() != 0 && program.bindings.push_constant_size == 0) {
|
||||||
Expect(Kind::UserData);
|
Expect(Kind::UserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,8 +263,10 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto has_user_storage = present[static_cast<size_t>(Kind::UserData)];
|
const auto has_user_storage = present[static_cast<size_t>(Kind::UserData)];
|
||||||
if ((!has_user_storage &&
|
if (program.bindings.buffer_offset_dword != program.bindings.user_data_registers.size() ||
|
||||||
program.bindings.push_constant_size != program.bindings.user_data_registers.size() * 4u) ||
|
program.bindings.buffer_offset_count != program.info.buffers.size() ||
|
||||||
|
(!has_user_storage &&
|
||||||
|
program.bindings.push_constant_size != program.bindings.ShaderDataDwords() * 4u) ||
|
||||||
(has_user_storage && program.bindings.push_constant_size != 0) ||
|
(has_user_storage && program.bindings.push_constant_size != 0) ||
|
||||||
!std::is_sorted(program.bindings.user_data_registers.begin(),
|
!std::is_sorted(program.bindings.user_data_registers.begin(),
|
||||||
program.bindings.user_data_registers.end()) ||
|
program.bindings.user_data_registers.end()) ||
|
||||||
@@ -408,10 +410,10 @@ bool ProgramRequiresExactSubgroupSize(const IR::Program& program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resources,
|
bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resources,
|
||||||
const ShaderVertexInputInfo* vertex_input_info,
|
const ShaderVertexInputInfo* vertex_input_info,
|
||||||
const ShaderPixelInputInfo* pixel_input_info,
|
const ShaderPixelInputInfo* pixel_input_info,
|
||||||
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
|
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
|
||||||
std::string* error) {
|
std::string* error) {
|
||||||
using namespace Emitter;
|
using namespace Emitter;
|
||||||
|
|
||||||
if (program.stage != ShaderType::Compute && program.stage != ShaderType::Vertex &&
|
if (program.stage != ShaderType::Compute && program.stage != ShaderType::Vertex &&
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ bool UserDataDwordIndex(const EmitterState& state, IR::Register reg, uint32_t& d
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EmitVsharpDwordLoad(EmitterState& state, uint32_t dword_index) {
|
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index) {
|
||||||
if (state.push_constant_variable != 0) {
|
if (state.push_constant_variable != 0) {
|
||||||
const auto pointer = state.builder.AllocateId();
|
const auto pointer = state.builder.AllocateId();
|
||||||
const auto value = state.builder.AllocateId();
|
const auto value = state.builder.AllocateId();
|
||||||
@@ -172,7 +172,7 @@ uint32_t InitialRegisterValue(const EmitterState& state, IR::Register reg) {
|
|||||||
uint32_t EmitInitialRegisterValue(EmitterState& state, IR::Register reg) {
|
uint32_t EmitInitialRegisterValue(EmitterState& state, IR::Register reg) {
|
||||||
uint32_t dword_index = 0;
|
uint32_t dword_index = 0;
|
||||||
if (UserDataDwordIndex(state, reg, dword_index)) {
|
if (UserDataDwordIndex(state, reg, dword_index)) {
|
||||||
return EmitVsharpDwordLoad(state, dword_index);
|
return EmitShaderDataDwordLoad(state, dword_index);
|
||||||
}
|
}
|
||||||
return ConstantU32(state, InitialRegisterValue(state, reg));
|
return ConstantU32(state, InitialRegisterValue(state, reg));
|
||||||
}
|
}
|
||||||
@@ -1064,6 +1064,7 @@ void EmitFunction(EmitterState& state, const IR::Program& program) {
|
|||||||
EmitComputeInputRegisters(state);
|
EmitComputeInputRegisters(state);
|
||||||
EmitPixelInputRegisters(state);
|
EmitPixelInputRegisters(state);
|
||||||
EmitVertexInputRegisters(state);
|
EmitVertexInputRegisters(state);
|
||||||
|
EmitStorageBufferOffsets(state);
|
||||||
if (state.dispatcher_fallback) {
|
if (state.dispatcher_fallback) {
|
||||||
EmitDispatcherFunction(state, program);
|
EmitDispatcherFunction(state, program);
|
||||||
state.builder.AddFunction({OpFunctionEnd});
|
state.builder.AddFunction({OpFunctionEnd});
|
||||||
|
|||||||
@@ -355,6 +355,7 @@ struct EmitterState {
|
|||||||
uint32_t storage_buffer_array_type = 0;
|
uint32_t storage_buffer_array_type = 0;
|
||||||
uint32_t ptr_storage_buffer_array = 0;
|
uint32_t ptr_storage_buffer_array = 0;
|
||||||
uint32_t storage_buffer_variable = 0;
|
uint32_t storage_buffer_variable = 0;
|
||||||
|
std::array<uint32_t, IR::ShaderInfo::MaxBuffers> storage_buffer_offsets {};
|
||||||
uint32_t address_memory_array_type = 0;
|
uint32_t address_memory_array_type = 0;
|
||||||
uint32_t ptr_address_memory_array = 0;
|
uint32_t ptr_address_memory_array = 0;
|
||||||
uint32_t address_memory_variable = 0;
|
uint32_t address_memory_variable = 0;
|
||||||
@@ -837,6 +838,8 @@ uint32_t EmitNotEqualZeroBool(EmitterState& state, uint32_t value);
|
|||||||
uint32_t EmitSelectU32Value(EmitterState& state, uint32_t condition, uint32_t true_value,
|
uint32_t EmitSelectU32Value(EmitterState& state, uint32_t condition, uint32_t true_value,
|
||||||
uint32_t false_value);
|
uint32_t false_value);
|
||||||
|
|
||||||
|
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index);
|
||||||
|
|
||||||
uint32_t EmitByteAddress(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
|
uint32_t EmitByteAddress(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
|
||||||
uint32_t src_count);
|
uint32_t src_count);
|
||||||
|
|
||||||
@@ -854,6 +857,8 @@ uint32_t EmitOptionalLogicalAndBool(EmitterState& state, uint32_t lhs, uint32_t
|
|||||||
|
|
||||||
bool IsStorageBufferMemoryKind(IR::ResourceKind kind);
|
bool IsStorageBufferMemoryKind(IR::ResourceKind kind);
|
||||||
|
|
||||||
|
void EmitStorageBufferOffsets(EmitterState& state);
|
||||||
|
|
||||||
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
||||||
uint32_t index, uint32_t offset, uint32_t soffset);
|
uint32_t index, uint32_t offset, uint32_t soffset);
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,17 @@ bool IsStorageBufferMemoryKind(IR::ResourceKind kind) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitStorageBufferOffsets(EmitterState& state) {
|
||||||
|
for (uint32_t i = 0; i < state.program.bindings.buffer_offset_count; i++) {
|
||||||
|
const auto word = EmitShaderDataDwordLoad(
|
||||||
|
state, state.program.bindings.buffer_offset_dword + i / 4u);
|
||||||
|
const auto shift = ConstantU32(state, (i % 4u) * 8u + 2u);
|
||||||
|
state.storage_buffer_offsets[i] = EmitBinaryU32(
|
||||||
|
state, OpBitwiseAnd,
|
||||||
|
EmitBinaryU32(state, OpShiftRightLogical, word, shift), ConstantU32(state, 0x3fu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
||||||
uint32_t index, uint32_t offset, uint32_t soffset) {
|
uint32_t index, uint32_t offset, uint32_t soffset) {
|
||||||
const auto& mem = inst.memory;
|
const auto& mem = inst.memory;
|
||||||
@@ -398,6 +409,15 @@ StorageBufferBindingForMemory(EmitterState& state, const IR::MemoryInfo& mem, ui
|
|||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t EmitStorageBufferIndex(EmitterState& state, const IR::MemoryInfo& mem, uint32_t index,
|
||||||
|
uint32_t use_pc) {
|
||||||
|
if (IsFlatMemoryKind(mem.kind)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
const auto binding = StorageBufferBindingForMemory(state, mem, use_pc);
|
||||||
|
return EmitAddU32(state, index, state.storage_buffer_offsets[binding.array_index]);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
||||||
uint32_t use_pc) {
|
uint32_t use_pc) {
|
||||||
if (IsFlatMemoryKind(mem.kind)) {
|
if (IsFlatMemoryKind(mem.kind)) {
|
||||||
@@ -422,7 +442,8 @@ uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryInfo& mem,
|
uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryInfo& mem,
|
||||||
uint32_t index, uint32_t use_pc) {
|
uint32_t index, uint32_t use_pc) {
|
||||||
|
index = EmitStorageBufferIndex(state, mem, index, use_pc);
|
||||||
const auto object = EmitStorageBufferObjectPointer(state, mem, use_pc);
|
const auto object = EmitStorageBufferObjectPointer(state, mem, use_pc);
|
||||||
const auto length = state.builder.AllocateId();
|
const auto length = state.builder.AllocateId();
|
||||||
const auto in_bounds = state.builder.AllocateId();
|
const auto in_bounds = state.builder.AllocateId();
|
||||||
@@ -432,7 +453,8 @@ uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryI
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EmitStorageBufferElementPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
uint32_t EmitStorageBufferElementPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
||||||
uint32_t index, uint32_t use_pc) {
|
uint32_t index, uint32_t use_pc) {
|
||||||
|
index = EmitStorageBufferIndex(state, mem, index, use_pc);
|
||||||
if (IsFlatMemoryKind(mem.kind)) {
|
if (IsFlatMemoryKind(mem.kind)) {
|
||||||
if (state.address_memory_variable == 0) {
|
if (state.address_memory_variable == 0) {
|
||||||
ExitDescriptorBindingFailure(state, IR::DescriptorBindingKind::AddressMemory,
|
ExitDescriptorBindingFailure(state, IR::DescriptorBindingKind::AddressMemory,
|
||||||
|
|||||||
@@ -995,6 +995,8 @@ static void ShaderAppendNativeSpecialization(std::vector<uint32_t>&
|
|||||||
ids.push_back(program.bindings.descriptor_set);
|
ids.push_back(program.bindings.descriptor_set);
|
||||||
ids.push_back(program.bindings.push_constant_offset);
|
ids.push_back(program.bindings.push_constant_offset);
|
||||||
ids.push_back(program.bindings.push_constant_size);
|
ids.push_back(program.bindings.push_constant_size);
|
||||||
|
ids.push_back(program.bindings.buffer_offset_dword);
|
||||||
|
ids.push_back(program.bindings.buffer_offset_count);
|
||||||
ids.push_back(static_cast<uint32_t>(program.bindings.user_data_registers.size()));
|
ids.push_back(static_cast<uint32_t>(program.bindings.user_data_registers.size()));
|
||||||
ids.insert(ids.end(), program.bindings.user_data_registers.begin(),
|
ids.insert(ids.end(), program.bindings.user_data_registers.begin(),
|
||||||
program.bindings.user_data_registers.end());
|
program.bindings.user_data_registers.end());
|
||||||
|
|||||||
@@ -1065,6 +1065,31 @@ void TestInvalidImagesMaterializeAsNull() {
|
|||||||
"invalid storage image descriptor was not normalized to null");
|
"invalid storage image descriptor was not normalized to null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestInvalidBuffersMaterializeAsNull() {
|
||||||
|
Program program;
|
||||||
|
program.stage = ShaderType::Compute;
|
||||||
|
program.user_data_count = 4;
|
||||||
|
program.blocks.resize(1);
|
||||||
|
program.blocks[0].instructions = {BufferUse(0x40, 0)};
|
||||||
|
Prepare(program);
|
||||||
|
|
||||||
|
constexpr std::array<uint32_t, 4> valid = {
|
||||||
|
0x0000100c, 0x00100000, 0x00000001, 0x0004dfac};
|
||||||
|
auto invalid = valid;
|
||||||
|
invalid[3] |= 1u << 30u;
|
||||||
|
std::string error;
|
||||||
|
ResourceSnapshot snapshot;
|
||||||
|
Check(MaterializeResources(program, {invalid}, snapshot, &error) &&
|
||||||
|
std::all_of(snapshot.buffers[0].dwords.begin(),
|
||||||
|
snapshot.buffers[0].dwords.begin() + 4,
|
||||||
|
[](uint32_t word) { return word == 0; }),
|
||||||
|
"invalid buffer descriptor was not normalized to null");
|
||||||
|
Check(MaterializeResources(program, {valid}, snapshot, &error) &&
|
||||||
|
std::equal(valid.begin(), valid.end(),
|
||||||
|
snapshot.buffers[0].dwords.begin()),
|
||||||
|
"valid buffer descriptor was normalized");
|
||||||
|
}
|
||||||
|
|
||||||
void TestMaterializationFailureIsTransactional() {
|
void TestMaterializationFailureIsTransactional() {
|
||||||
Program program;
|
Program program;
|
||||||
program.blocks.resize(1);
|
program.blocks.resize(1);
|
||||||
@@ -1381,6 +1406,9 @@ void TestNativeBindingLayout() {
|
|||||||
FindBinding(program.bindings, DescriptorBindingKind::StorageUint2DArray);
|
FindBinding(program.bindings, DescriptorBindingKind::StorageUint2DArray);
|
||||||
const auto *samplers =
|
const auto *samplers =
|
||||||
FindBinding(program.bindings, DescriptorBindingKind::Samplers);
|
FindBinding(program.bindings, DescriptorBindingKind::Samplers);
|
||||||
|
const auto *shader_data =
|
||||||
|
FindBinding(program.bindings, DescriptorBindingKind::UserData);
|
||||||
|
const auto shader_data_dwords = program.bindings.ShaderDataDwords();
|
||||||
Check(
|
Check(
|
||||||
program.bindings.descriptor_set == 3 && buffers != nullptr &&
|
program.bindings.descriptor_set == 3 && buffers != nullptr &&
|
||||||
sampled2d != nullptr && sampled_array != nullptr &&
|
sampled2d != nullptr && sampled_array != nullptr &&
|
||||||
@@ -1393,12 +1421,19 @@ void TestNativeBindingLayout() {
|
|||||||
sampled2d->resources == std::vector<uint32_t>{0} &&
|
sampled2d->resources == std::vector<uint32_t>{0} &&
|
||||||
sampled_array->resources == std::vector<uint32_t>{1} &&
|
sampled_array->resources == std::vector<uint32_t>{1} &&
|
||||||
storage3d->resources == std::vector<uint32_t>{2} &&
|
storage3d->resources == std::vector<uint32_t>{2} &&
|
||||||
storage_uint_array->resources == std::vector<uint32_t>{3} &&
|
storage_uint_array->resources == std::vector<uint32_t>{3} &&
|
||||||
samplers->resources == std::vector<uint32_t>{0} &&
|
samplers->resources == std::vector<uint32_t>{0} &&
|
||||||
!program.bindings.user_data_registers.empty() &&
|
!program.bindings.user_data_registers.empty() &&
|
||||||
program.bindings.push_constant_size != 0 &&
|
program.bindings.buffer_offset_dword ==
|
||||||
FindBinding(program.bindings, DescriptorBindingKind::FlattenedSrt) ==
|
program.bindings.user_data_registers.size() &&
|
||||||
nullptr &&
|
program.bindings.buffer_offset_count == 1 &&
|
||||||
|
((program.bindings.push_constant_size ==
|
||||||
|
shader_data_dwords * sizeof(uint32_t) &&
|
||||||
|
shader_data == nullptr) ||
|
||||||
|
(program.bindings.push_constant_size == 0 &&
|
||||||
|
shader_data != nullptr && shader_data->binding == 6)) &&
|
||||||
|
FindBinding(program.bindings, DescriptorBindingKind::FlattenedSrt) ==
|
||||||
|
nullptr &&
|
||||||
program.binding_layout_complete,
|
program.binding_layout_complete,
|
||||||
"native binding allocator did not preserve dense typed resource groups");
|
"native binding allocator did not preserve dense typed resource groups");
|
||||||
}
|
}
|
||||||
@@ -1907,6 +1942,7 @@ int main() {
|
|||||||
RUN(TestSrtPatchPlanValidation);
|
RUN(TestSrtPatchPlanValidation);
|
||||||
RUN(TestMaterializationSharesReadConstEvaluation);
|
RUN(TestMaterializationSharesReadConstEvaluation);
|
||||||
RUN(TestInvalidImagesMaterializeAsNull);
|
RUN(TestInvalidImagesMaterializeAsNull);
|
||||||
|
RUN(TestInvalidBuffersMaterializeAsNull);
|
||||||
RUN(TestMaterializationFailureIsTransactional);
|
RUN(TestMaterializationFailureIsTransactional);
|
||||||
RUN(TestResourceSpecializationIsTypedAndTransactional);
|
RUN(TestResourceSpecializationIsTypedAndTransactional);
|
||||||
RUN(TestRuntimeSpecializationCoversBakedBufferAndAddressFields);
|
RUN(TestRuntimeSpecializationCoversBakedBufferAndAddressFields);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#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/recompiler/SpirvBuilder.h"
|
#include "graphics/shader/recompiler/SpirvBuilder.h"
|
||||||
|
#include "graphics/shader/recompiler/SpirvEmitter.h"
|
||||||
#include "graphics/shader/shader.h"
|
#include "graphics/shader/shader.h"
|
||||||
#include "kernel/memory.h"
|
#include "kernel/memory.h"
|
||||||
|
|
||||||
@@ -723,6 +724,8 @@ struct TestCase {
|
|||||||
u32 image_descriptor_swizzle = DstSel(4, 5, 6, 7);
|
u32 image_descriptor_swizzle = DstSel(4, 5, 6, 7);
|
||||||
bool compile_only = false;
|
bool compile_only = false;
|
||||||
size_t storage_buffer_range_dwords = 0;
|
size_t storage_buffer_range_dwords = 0;
|
||||||
|
std::vector<u32> storage_buffer_offsets;
|
||||||
|
bool force_shader_data_storage = false;
|
||||||
std::optional<uint64_t> flat_memory_base;
|
std::optional<uint64_t> flat_memory_base;
|
||||||
std::vector<u32> gds_initial;
|
std::vector<u32> gds_initial;
|
||||||
std::vector<u32> expected_gds;
|
std::vector<u32> expected_gds;
|
||||||
@@ -849,6 +852,29 @@ CompiledShader CompileCase(const TestCase &test) {
|
|||||||
if (!ShaderRecompiler::TryRecompile(test.code, options, result, &error)) {
|
if (!ShaderRecompiler::TryRecompile(test.code, options, result, &error)) {
|
||||||
Fail(test.name, "decode/IR", error.c_str());
|
Fail(test.name, "decode/IR", error.c_str());
|
||||||
}
|
}
|
||||||
|
if (test.force_shader_data_storage) {
|
||||||
|
result.program.bindings = {};
|
||||||
|
result.program.binding_layout_complete = false;
|
||||||
|
if (!ShaderRecompiler::IR::AllocateBindings(
|
||||||
|
result.program, {.max_push_dwords = 0}, &error)) {
|
||||||
|
Fail(test.name, "binding layout", error.c_str());
|
||||||
|
}
|
||||||
|
const auto *shader_data = ShaderRecompiler::IR::FindBinding(
|
||||||
|
result.program.bindings,
|
||||||
|
ShaderRecompiler::IR::DescriptorBindingKind::UserData);
|
||||||
|
Require(test.name, "binding layout",
|
||||||
|
result.program.bindings.user_data_registers.empty() &&
|
||||||
|
result.program.bindings.push_constant_size == 0 &&
|
||||||
|
shader_data != nullptr,
|
||||||
|
"offset-only shader data did not use its storage fallback");
|
||||||
|
std::vector<u32> storage_spirv;
|
||||||
|
if (!ShaderRecompiler::Spirv::EmitProgram(
|
||||||
|
result.program, result.resources, nullptr, nullptr,
|
||||||
|
options.compute_input_info, storage_spirv, &error)) {
|
||||||
|
Fail(test.name, "SPIR-V emit", error.c_str());
|
||||||
|
}
|
||||||
|
result.spirv = std::move(storage_spirv);
|
||||||
|
}
|
||||||
Require(test.name, "SPIR-V emit", !result.spirv.empty(),
|
Require(test.name, "SPIR-V emit", !result.spirv.empty(),
|
||||||
"recompiler returned empty SPIR-V");
|
"recompiler returned empty SPIR-V");
|
||||||
ValidateSpirv(test.name, result.spirv);
|
ValidateSpirv(test.name, result.spirv);
|
||||||
@@ -858,6 +884,16 @@ CompiledShader CompileCase(const TestCase &test) {
|
|||||||
packed_user_data.push_back(
|
packed_user_data.push_back(
|
||||||
result.resources.user_data[reg - result.program.user_data_base]);
|
result.resources.user_data[reg - result.program.user_data_base]);
|
||||||
}
|
}
|
||||||
|
packed_user_data.resize(result.program.bindings.ShaderDataDwords());
|
||||||
|
for (u32 i = 0; i < result.program.bindings.buffer_offset_count; i++) {
|
||||||
|
const auto offset = i < test.storage_buffer_offsets.size()
|
||||||
|
? test.storage_buffer_offsets[i]
|
||||||
|
: 0u;
|
||||||
|
Require(test.name, "shader data", offset % sizeof(u32) == 0 && offset < 256,
|
||||||
|
"storage buffer offset is not representable");
|
||||||
|
packed_user_data[result.program.bindings.buffer_offset_dword + i / 4u] |=
|
||||||
|
offset << ((i % 4u) * 8u);
|
||||||
|
}
|
||||||
return {std::move(result.spirv), std::move(result.program),
|
return {std::move(result.spirv), std::move(result.program),
|
||||||
std::move(result.resources.flattened_srt),
|
std::move(result.resources.flattened_srt),
|
||||||
std::move(packed_user_data)};
|
std::move(packed_user_data)};
|
||||||
@@ -924,6 +960,7 @@ CompiledShader CompileFragmentCase(const GraphicsCase &test) {
|
|||||||
packed_user_data.push_back(
|
packed_user_data.push_back(
|
||||||
result.resources.user_data[reg - result.program.user_data_base]);
|
result.resources.user_data[reg - result.program.user_data_base]);
|
||||||
}
|
}
|
||||||
|
packed_user_data.resize(result.program.bindings.ShaderDataDwords());
|
||||||
return {std::move(result.spirv), std::move(result.program),
|
return {std::move(result.spirv), std::move(result.program),
|
||||||
std::move(result.resources.flattened_srt),
|
std::move(result.resources.flattened_srt),
|
||||||
std::move(packed_user_data)};
|
std::move(packed_user_data)};
|
||||||
@@ -1785,9 +1822,8 @@ public:
|
|||||||
const auto depth_attachment = depth.FindView(depth_attachment_info);
|
const auto depth_attachment = depth.FindView(depth_attachment_info);
|
||||||
Require(name, "depth views",
|
Require(name, "depth views",
|
||||||
depth_first != nullptr && depth_again == depth_first &&
|
depth_first != nullptr && depth_again == depth_first &&
|
||||||
depth_alias == depth_first &&
|
depth_alias == depth_first && depth_array != nullptr &&
|
||||||
depth_array != nullptr && depth_array != depth_first &&
|
depth_array != depth_first && depth_attachment != nullptr &&
|
||||||
depth_attachment != nullptr &&
|
|
||||||
depth_attachment != depth_array &&
|
depth_attachment != depth_array &&
|
||||||
depth.views.views.size() == 3,
|
depth.views.views.size() == 3,
|
||||||
"unified depth view cache lost sampled/attachment identity");
|
"unified depth view cache lost sampled/attachment identity");
|
||||||
@@ -2547,8 +2583,7 @@ public:
|
|||||||
auto uncompressed_block = MakeLinearDesc(
|
auto uncompressed_block = MakeLinearDesc(
|
||||||
base + block_alias_offset, sizeof(block_alias_data),
|
base + block_alias_offset, sizeof(block_alias_data),
|
||||||
vk::Format::eR32G32B32A32Uint,
|
vk::Format::eR32G32B32A32Uint,
|
||||||
Prospero::GpuEnumValue(
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32_32_32UInt),
|
||||||
Prospero::BufferFormat::k32_32_32_32UInt),
|
|
||||||
Prospero::ImageType::kColor2D, {1, 1, 1}, 1, 16, 1);
|
Prospero::ImageType::kColor2D, {1, 1, 1}, 1, 16, 1);
|
||||||
const auto uncompressed_block_image =
|
const auto uncompressed_block_image =
|
||||||
texture_cache.FindImage(uncompressed_block);
|
texture_cache.FindImage(uncompressed_block);
|
||||||
@@ -2568,15 +2603,16 @@ public:
|
|||||||
std::array<uint32_t, block_alias_data.size()> block_alias_after{};
|
std::array<uint32_t, block_alias_data.size()> block_alias_after{};
|
||||||
std::memcpy(block_alias_after.data(), memory + block_alias_offset,
|
std::memcpy(block_alias_after.data(), memory + block_alias_offset,
|
||||||
sizeof(block_alias_after));
|
sizeof(block_alias_after));
|
||||||
Require(name, "compressed view expansion",
|
Require(
|
||||||
compressed_block_image &&
|
name, "compressed view expansion",
|
||||||
compressed_block_image != uncompressed_block_image &&
|
compressed_block_image &&
|
||||||
texture_cache.GetImage(compressed_block_image)
|
compressed_block_image != uncompressed_block_image &&
|
||||||
.backing.format == vk::Format::eBc3UnormBlock &&
|
texture_cache.GetImage(compressed_block_image).backing.format ==
|
||||||
compressed_block_download &&
|
vk::Format::eBc3UnormBlock &&
|
||||||
block_alias_after == block_alias_data,
|
compressed_block_download &&
|
||||||
"size-compatible compressed alias did not preserve its native "
|
block_alias_after == block_alias_data,
|
||||||
"contents");
|
"size-compatible compressed alias did not preserve its native "
|
||||||
|
"contents");
|
||||||
|
|
||||||
ImageInfo resolve_source_info{};
|
ImageInfo resolve_source_info{};
|
||||||
resolve_source_info.pixel_format = vk::Format::eR8G8B8A8Unorm;
|
resolve_source_info.pixel_format = vk::Format::eR8G8B8A8Unorm;
|
||||||
@@ -3317,8 +3353,10 @@ public:
|
|||||||
name, "unformatted buffer/image alias",
|
name, "unformatted buffer/image alias",
|
||||||
unformatted_alias_buffer.buffer != nullptr &&
|
unformatted_alias_buffer.buffer != nullptr &&
|
||||||
texture_cache.GetImage(unformatted_alias_image).IsGpuModified() &&
|
texture_cache.GetImage(unformatted_alias_image).IsGpuModified() &&
|
||||||
!texture_cache.GetImage(unformatted_alias_image).IsBufferModified(),
|
!texture_cache.GetImage(unformatted_alias_image)
|
||||||
"read-only unformatted buffer alias did not follow ordinary BufferCache acquisition");
|
.IsBufferModified(),
|
||||||
|
"read-only unformatted buffer alias did not follow ordinary "
|
||||||
|
"BufferCache acquisition");
|
||||||
if (unformatted_alias_buffer.owner != nullptr) {
|
if (unformatted_alias_buffer.owner != nullptr) {
|
||||||
command.RetainResourceUntilFence(unformatted_alias_buffer.owner);
|
command.RetainResourceUntilFence(unformatted_alias_buffer.owner);
|
||||||
}
|
}
|
||||||
@@ -5243,15 +5281,23 @@ public:
|
|||||||
"ownership became visible");
|
"ownership became visible");
|
||||||
|
|
||||||
constexpr uint64_t phased_depth_address = base + 0x90000;
|
constexpr uint64_t phased_depth_address = base + 0x90000;
|
||||||
|
constexpr uint64_t phased_stencil_address = base + 0xa0000;
|
||||||
constexpr uint64_t phased_htile_address = base + 0xb0000;
|
constexpr uint64_t phased_htile_address = base + 0xb0000;
|
||||||
HW::DepthRenderTarget phased_depth_target{};
|
HW::DepthRenderTarget phased_depth_target{};
|
||||||
phased_depth_target.z_info.format =
|
phased_depth_target.z_info.format =
|
||||||
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F);
|
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F);
|
||||||
phased_depth_target.z_info.tile_surface_enable = true;
|
phased_depth_target.z_info.texture_compatibility =
|
||||||
phased_depth_target.z_info.zrange_precision = 1;
|
Prospero::TextureCompatiblePlaneCompression::kEnable;
|
||||||
phased_depth_target.stencil_info.tile_stencil_disable = true;
|
phased_depth_target.z_info.htile_acceleration = true;
|
||||||
|
phased_depth_target.z_info.z_compare_base = Prospero::ZCompareBase::kZMax;
|
||||||
|
phased_depth_target.stencil_info.format =
|
||||||
|
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt);
|
||||||
|
phased_depth_target.stencil_info.texture_compatibility =
|
||||||
|
Prospero::TextureCompatibleStencil::kEnable;
|
||||||
phased_depth_target.z_read_base_addr = phased_depth_address;
|
phased_depth_target.z_read_base_addr = phased_depth_address;
|
||||||
phased_depth_target.z_write_base_addr = phased_depth_address;
|
phased_depth_target.z_write_base_addr = phased_depth_address;
|
||||||
|
phased_depth_target.stencil_read_base_addr = phased_stencil_address;
|
||||||
|
phased_depth_target.stencil_write_base_addr = phased_stencil_address;
|
||||||
phased_depth_target.htile_data_base_addr = phased_htile_address;
|
phased_depth_target.htile_data_base_addr = phased_htile_address;
|
||||||
phased_depth_target.size.valid = true;
|
phased_depth_target.size.valid = true;
|
||||||
registers.SetDepthRenderTarget(phased_depth_target);
|
registers.SetDepthRenderTarget(phased_depth_target);
|
||||||
@@ -5265,16 +5311,34 @@ public:
|
|||||||
RenderDepthInfo phased_depth{};
|
RenderDepthInfo phased_depth{};
|
||||||
RenderExecutorTestAccess::ResolveRenderDepthTarget(
|
RenderExecutorTestAccess::ResolveRenderDepthTarget(
|
||||||
executor, 1, scheduler.Current(), phased_depth);
|
executor, 1, scheduler.Current(), phased_depth);
|
||||||
|
auto non_texture_compatible_target = phased_depth_target;
|
||||||
|
non_texture_compatible_target.z_info.texture_compatibility =
|
||||||
|
Prospero::TextureCompatiblePlaneCompression::kDisable;
|
||||||
|
non_texture_compatible_target.stencil_info.texture_compatibility =
|
||||||
|
Prospero::TextureCompatibleStencil::kDisable;
|
||||||
|
registers.SetDepthRenderTarget(non_texture_compatible_target);
|
||||||
|
RenderDepthInfo non_texture_compatible_depth{};
|
||||||
|
RenderExecutorTestAccess::ResolveRenderDepthTarget(
|
||||||
|
executor, 1, scheduler.Current(), non_texture_compatible_depth);
|
||||||
Require(
|
Require(
|
||||||
name, "HTile discovery purity",
|
name, "depth texture compatibility identity",
|
||||||
phased_depth.image_id && phased_depth.htile &&
|
phased_depth.image_id && phased_depth.htile &&
|
||||||
|
non_texture_compatible_depth.image_id == phased_depth.image_id &&
|
||||||
|
non_texture_compatible_depth.desc.info.data ==
|
||||||
|
phased_depth.desc.info.data &&
|
||||||
|
non_texture_compatible_depth.desc.info.stencil ==
|
||||||
|
phased_depth.desc.info.stencil &&
|
||||||
|
non_texture_compatible_depth.desc.info.metadata.range ==
|
||||||
|
phased_depth.desc.info.metadata.range &&
|
||||||
|
phased_depth.desc.info.metadata.stencil_compressed &&
|
||||||
!phased_depth.depth_clear_enable &&
|
!phased_depth.depth_clear_enable &&
|
||||||
!phased_depth.depth_meta_clear_enable &&
|
!phased_depth.depth_meta_clear_enable &&
|
||||||
!texture_cache.IsMeta(phased_depth.htile_buffer_vaddr) &&
|
!texture_cache.IsMeta(phased_depth.htile_buffer_vaddr) &&
|
||||||
!texture_cache.GetImage(phased_depth.image_id).IsGpuModified() &&
|
!texture_cache.GetImage(phased_depth.image_id).IsGpuModified() &&
|
||||||
!texture_cache.GetImage(phased_depth.image_id).usage.depth_target,
|
!texture_cache.GetImage(phased_depth.image_id).usage.depth_target,
|
||||||
"depth discovery registered, consumed, or GPU-owned HTile "
|
"valid PS5 texture-compatibility policy changed logical depth image "
|
||||||
"state before final acquisition");
|
"identity or discovery side effects");
|
||||||
|
registers.SetDepthRenderTarget(phased_depth_target);
|
||||||
RenderColorInfo no_color{};
|
RenderColorInfo no_color{};
|
||||||
auto phased_rendering = RenderExecutorTestAccess::AcquireRenderTargets(
|
auto phased_rendering = RenderExecutorTestAccess::AcquireRenderTargets(
|
||||||
executor, scheduler.Current(), &no_color, 0, phased_depth);
|
executor, scheduler.Current(), &no_color, 0, phased_depth);
|
||||||
@@ -5340,8 +5404,8 @@ public:
|
|||||||
"replacement");
|
"replacement");
|
||||||
|
|
||||||
constexpr uint64_t array_target_address = base + 0xd0000;
|
constexpr uint64_t array_target_address = base + 0xd0000;
|
||||||
auto array_target =
|
auto array_target = make_target_desc(array_target_address,
|
||||||
make_target_desc(array_target_address, target_mip_size, {128, 128, 1});
|
target_mip_size, {128, 128, 1});
|
||||||
const auto array_target_id = texture_cache.FindImage(array_target);
|
const auto array_target_id = texture_cache.FindImage(array_target);
|
||||||
const auto array_target_owner =
|
const auto array_target_owner =
|
||||||
TextureCacheTestAccess::Owner(texture_cache, array_target_id);
|
TextureCacheTestAccess::Owner(texture_cache, array_target_id);
|
||||||
@@ -5353,16 +5417,14 @@ public:
|
|||||||
const auto encoded_array_address = array_target_address >> 8u;
|
const auto encoded_array_address = array_target_address >> 8u;
|
||||||
constexpr auto array_format =
|
constexpr auto array_format =
|
||||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt);
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt);
|
||||||
array_texture.fields[0] =
|
array_texture.fields[0] = static_cast<uint32_t>(encoded_array_address);
|
||||||
static_cast<uint32_t>(encoded_array_address);
|
|
||||||
array_texture.fields[1] =
|
array_texture.fields[1] =
|
||||||
static_cast<uint32_t>(encoded_array_address >> 32u) |
|
static_cast<uint32_t>(encoded_array_address >> 32u) |
|
||||||
(array_format << 20u) | (3u << 30u);
|
(array_format << 20u) | (3u << 30u);
|
||||||
array_texture.fields[2] = (127u >> 2u) | (127u << 14u);
|
array_texture.fields[2] = (127u >> 2u) | (127u << 14u);
|
||||||
array_texture.fields[3] =
|
array_texture.fields[3] =
|
||||||
DstSel(4, 5, 6, 7) | (linear << 20u) |
|
DstSel(4, 5, 6, 7) | (linear << 20u) |
|
||||||
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray)
|
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) << 28u);
|
||||||
<< 28u);
|
|
||||||
array_texture.fields[4] = 1;
|
array_texture.fields[4] = 1;
|
||||||
|
|
||||||
ShaderRecompiler::IR::Program array_program{};
|
ShaderRecompiler::IR::Program array_program{};
|
||||||
@@ -5388,13 +5450,11 @@ public:
|
|||||||
std::move(array_snapshot))};
|
std::move(array_snapshot))};
|
||||||
|
|
||||||
auto array_binding = executor.PrepareBindings(
|
auto array_binding = executor.PrepareBindings(
|
||||||
scheduler.Current(), array_runtime,
|
scheduler.Current(), array_runtime, vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
|
DescriptorCache::Stage::Compute);
|
||||||
executor.RebindImages(scheduler.Current(), array_binding);
|
executor.RebindImages(scheduler.Current(), array_binding);
|
||||||
const auto expanded_array_id =
|
const auto expanded_array_id = array_binding.resources.images[0].image_id;
|
||||||
array_binding.resources.images[0].image_id;
|
const auto &expanded_array = texture_cache.GetImage(expanded_array_id);
|
||||||
const auto &expanded_array =
|
|
||||||
texture_cache.GetImage(expanded_array_id);
|
|
||||||
Require(
|
Require(
|
||||||
name, "2D target to array backing expansion",
|
name, "2D target to array backing expansion",
|
||||||
array_target_view != nullptr && array_target_owner != nullptr &&
|
array_target_view != nullptr && array_target_owner != nullptr &&
|
||||||
@@ -5424,27 +5484,26 @@ public:
|
|||||||
auto array_rendering = RenderExecutorTestAccess::AcquireRenderTargets(
|
auto array_rendering = RenderExecutorTestAccess::AcquireRenderTargets(
|
||||||
executor, scheduler.Current(), &rebound_array_target, 1,
|
executor, scheduler.Current(), &rebound_array_target, 1,
|
||||||
no_array_depth);
|
no_array_depth);
|
||||||
Require(
|
Require(name, "expanded array target rebind",
|
||||||
name, "expanded array target rebind",
|
rebound_array_target.image_id == expanded_array_id &&
|
||||||
rebound_array_target.image_id == expanded_array_id &&
|
rebound_array_target.image_view != nullptr &&
|
||||||
rebound_array_target.image_view != nullptr &&
|
array_rendering.num_color_attachments == 1 &&
|
||||||
array_rendering.num_color_attachments == 1 &&
|
array_rendering.color_attachments[0].image_view ==
|
||||||
array_rendering.color_attachments[0].image_view ==
|
rebound_array_target.image_view &&
|
||||||
rebound_array_target.image_view &&
|
array_rendering.width == 128 &&
|
||||||
array_rendering.width == 128 && array_rendering.height == 128 &&
|
array_rendering.height == 128 &&
|
||||||
array_rendering.num_layers == 1 &&
|
array_rendering.num_layers == 1 &&
|
||||||
texture_cache.GetImage(expanded_array_id).binding.is_bound &&
|
texture_cache.GetImage(expanded_array_id).binding.is_bound &&
|
||||||
texture_cache.GetImage(expanded_array_id).binding.is_target,
|
texture_cache.GetImage(expanded_array_id).binding.is_target,
|
||||||
"the retained single-layer target did not rebind to the expanded "
|
"the retained single-layer target did not rebind to the expanded "
|
||||||
"backing");
|
"backing");
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
|
||||||
auto colliding_msaa_texture = array_texture;
|
auto colliding_msaa_texture = array_texture;
|
||||||
colliding_msaa_texture.fields[3] =
|
colliding_msaa_texture.fields[3] =
|
||||||
DstSel(4, 5, 6, 7) | (1u << 16u) |
|
DstSel(4, 5, 6, 7) | (1u << 16u) |
|
||||||
(Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) << 20u) |
|
(Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) << 20u) |
|
||||||
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DMsaa)
|
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DMsaa) << 28u);
|
||||||
<< 28u);
|
|
||||||
colliding_msaa_texture.fields[4] = 0;
|
colliding_msaa_texture.fields[4] = 0;
|
||||||
colliding_msaa_texture.fields[5] = (7u << 20u) | (1u << 4u);
|
colliding_msaa_texture.fields[5] = (7u << 20u) | (1u << 4u);
|
||||||
ShaderRecompiler::IR::DescriptorValue colliding_msaa_descriptor{};
|
ShaderRecompiler::IR::DescriptorValue colliding_msaa_descriptor{};
|
||||||
@@ -5501,26 +5560,22 @@ public:
|
|||||||
|
|
||||||
auto msaa_texture = array_texture;
|
auto msaa_texture = array_texture;
|
||||||
const auto encoded_msaa_address = msaa_target_address >> 8u;
|
const auto encoded_msaa_address = msaa_target_address >> 8u;
|
||||||
msaa_texture.fields[0] =
|
msaa_texture.fields[0] = static_cast<uint32_t>(encoded_msaa_address);
|
||||||
static_cast<uint32_t>(encoded_msaa_address);
|
|
||||||
msaa_texture.fields[1] =
|
msaa_texture.fields[1] =
|
||||||
static_cast<uint32_t>(encoded_msaa_address >> 32u) |
|
static_cast<uint32_t>(encoded_msaa_address >> 32u) |
|
||||||
(array_format << 20u) | (3u << 30u);
|
(array_format << 20u) | (3u << 30u);
|
||||||
msaa_texture.fields[3] =
|
msaa_texture.fields[3] =
|
||||||
DstSel(4, 5, 6, 7) | (2u << 16u) |
|
DstSel(4, 5, 6, 7) | (2u << 16u) |
|
||||||
(Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) << 20u) |
|
(Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) << 20u) |
|
||||||
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DMsaa)
|
(Prospero::GpuEnumValue(Prospero::ImageType::kColor2DMsaa) << 28u);
|
||||||
<< 28u);
|
|
||||||
msaa_texture.fields[4] = 0;
|
msaa_texture.fields[4] = 0;
|
||||||
msaa_texture.fields[5] = (7u << 20u) | (2u << 4u);
|
msaa_texture.fields[5] = (7u << 20u) | (2u << 4u);
|
||||||
ShaderRecompiler::IR::DescriptorValue msaa_descriptor{};
|
ShaderRecompiler::IR::DescriptorValue msaa_descriptor{};
|
||||||
std::copy(std::begin(msaa_texture.fields),
|
std::copy(std::begin(msaa_texture.fields), std::end(msaa_texture.fields),
|
||||||
std::end(msaa_texture.fields),
|
|
||||||
msaa_descriptor.dwords.begin());
|
msaa_descriptor.dwords.begin());
|
||||||
msaa_descriptor.dword_count = 8;
|
msaa_descriptor.dword_count = 8;
|
||||||
auto msaa_program =
|
auto msaa_program = std::make_shared<ShaderRecompiler::IR::Program>(
|
||||||
std::make_shared<ShaderRecompiler::IR::Program>(
|
*array_runtime.program);
|
||||||
*array_runtime.program);
|
|
||||||
msaa_program->info.images[0].dimension =
|
msaa_program->info.images[0].dimension =
|
||||||
ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||||
auto msaa_snapshot =
|
auto msaa_snapshot =
|
||||||
@@ -5529,8 +5584,8 @@ public:
|
|||||||
ShaderStageRuntime msaa_runtime{std::move(msaa_program),
|
ShaderStageRuntime msaa_runtime{std::move(msaa_program),
|
||||||
std::move(msaa_snapshot)};
|
std::move(msaa_snapshot)};
|
||||||
auto msaa_binding = executor.PrepareBindings(
|
auto msaa_binding = executor.PrepareBindings(
|
||||||
scheduler.Current(), msaa_runtime,
|
scheduler.Current(), msaa_runtime, vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
|
DescriptorCache::Stage::Compute);
|
||||||
executor.RebindImages(scheduler.Current(), msaa_binding);
|
executor.RebindImages(scheduler.Current(), msaa_binding);
|
||||||
const auto &resolved_msaa = msaa_binding.resources.images[0];
|
const auto &resolved_msaa = msaa_binding.resources.images[0];
|
||||||
Require(
|
Require(
|
||||||
@@ -5538,10 +5593,8 @@ public:
|
|||||||
msaa_target_view != nullptr &&
|
msaa_target_view != nullptr &&
|
||||||
resolved_msaa.image_id == msaa_target_id &&
|
resolved_msaa.image_id == msaa_target_id &&
|
||||||
resolved_msaa.image_view != nullptr &&
|
resolved_msaa.image_view != nullptr &&
|
||||||
resolved_msaa.desc.info.type ==
|
resolved_msaa.desc.info.type == Prospero::ImageType::kColor2D &&
|
||||||
Prospero::ImageType::kColor2D &&
|
resolved_msaa.desc.info.resources == ImageSubresources{1, 1} &&
|
||||||
resolved_msaa.desc.info.resources ==
|
|
||||||
ImageSubresources{1, 1} &&
|
|
||||||
resolved_msaa.desc.info.samples == msaa_samples &&
|
resolved_msaa.desc.info.samples == msaa_samples &&
|
||||||
resolved_msaa.desc.info.data.size == 0x40000 &&
|
resolved_msaa.desc.info.data.size == 0x40000 &&
|
||||||
resolved_msaa.desc.view_info.level_count == 1 &&
|
resolved_msaa.desc.view_info.level_count == 1 &&
|
||||||
@@ -5562,9 +5615,8 @@ public:
|
|||||||
std::end(msaa_array_texture.fields),
|
std::end(msaa_array_texture.fields),
|
||||||
msaa_array_descriptor.dwords.begin());
|
msaa_array_descriptor.dwords.begin());
|
||||||
msaa_array_descriptor.dword_count = 8;
|
msaa_array_descriptor.dword_count = 8;
|
||||||
auto msaa_array_program =
|
auto msaa_array_program = std::make_shared<ShaderRecompiler::IR::Program>(
|
||||||
std::make_shared<ShaderRecompiler::IR::Program>(
|
*msaa_runtime.program);
|
||||||
*msaa_runtime.program);
|
|
||||||
msaa_array_program->info.images[0].dimension =
|
msaa_array_program->info.images[0].dimension =
|
||||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
|
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
|
||||||
auto msaa_array_snapshot =
|
auto msaa_array_snapshot =
|
||||||
@@ -5576,26 +5628,24 @@ public:
|
|||||||
scheduler.Current(), msaa_array_runtime,
|
scheduler.Current(), msaa_array_runtime,
|
||||||
vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
|
vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
|
||||||
executor.RebindImages(scheduler.Current(), msaa_array_binding);
|
executor.RebindImages(scheduler.Current(), msaa_array_binding);
|
||||||
const auto &resolved_msaa_array =
|
const auto &resolved_msaa_array = msaa_array_binding.resources.images[0];
|
||||||
msaa_array_binding.resources.images[0];
|
Require(name, "MSAA array backing expansion",
|
||||||
Require(
|
resolved_msaa_array.image_id != msaa_target_id &&
|
||||||
name, "MSAA array backing expansion",
|
resolved_msaa_array.image_view != nullptr &&
|
||||||
resolved_msaa_array.image_id != msaa_target_id &&
|
resolved_msaa_array.desc.info.type ==
|
||||||
resolved_msaa_array.image_view != nullptr &&
|
Prospero::ImageType::kColor2D &&
|
||||||
resolved_msaa_array.desc.info.type ==
|
resolved_msaa_array.desc.info.resources ==
|
||||||
Prospero::ImageType::kColor2D &&
|
ImageSubresources{1, 2} &&
|
||||||
resolved_msaa_array.desc.info.resources ==
|
resolved_msaa_array.desc.info.samples == msaa_samples &&
|
||||||
ImageSubresources{1, 2} &&
|
resolved_msaa_array.desc.info.data.size == 0x80000 &&
|
||||||
resolved_msaa_array.desc.info.samples == msaa_samples &&
|
resolved_msaa_array.desc.view_info.type ==
|
||||||
resolved_msaa_array.desc.info.data.size == 0x80000 &&
|
vk::ImageViewType::e2DArray &&
|
||||||
resolved_msaa_array.desc.view_info.type ==
|
resolved_msaa_array.desc.view_info.layer_count == 2 &&
|
||||||
vk::ImageViewType::e2DArray &&
|
texture_cache.GetImage(resolved_msaa_array.image_id)
|
||||||
resolved_msaa_array.desc.view_info.layer_count == 2 &&
|
.backing.layers == 2 &&
|
||||||
texture_cache.GetImage(resolved_msaa_array.image_id)
|
texture_cache.GetImage(resolved_msaa_array.image_id)
|
||||||
.backing.layers == 2 &&
|
.backing.samples == msaa_samples,
|
||||||
texture_cache.GetImage(resolved_msaa_array.image_id)
|
"MSAA array view did not expand the matching Color2D backing");
|
||||||
.backing.samples == msaa_samples,
|
|
||||||
"MSAA array view did not expand the matching Color2D backing");
|
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
|
||||||
ImageDesc depth{};
|
ImageDesc depth{};
|
||||||
@@ -5902,14 +5952,14 @@ public:
|
|||||||
std::move(stencil_storage_snapshot))};
|
std::move(stencil_storage_snapshot))};
|
||||||
auto storage_redirected = executor.PrepareBindings(
|
auto storage_redirected = executor.PrepareBindings(
|
||||||
scheduler.Current(), stencil_storage_runtime,
|
scheduler.Current(), stencil_storage_runtime,
|
||||||
vk::ShaderStageFlagBits::eCompute,
|
vk::ShaderStageFlagBits::eCompute, DescriptorCache::Stage::Compute);
|
||||||
DescriptorCache::Stage::Compute);
|
|
||||||
executor.RebindImages(scheduler.Current(), storage_redirected);
|
executor.RebindImages(scheduler.Current(), storage_redirected);
|
||||||
Require(name, "storage stencil acquisition",
|
Require(
|
||||||
storage_redirected.resources.images[0].image_id == depth_id &&
|
name, "storage stencil acquisition",
|
||||||
storage_redirected.resources.images[0].image_view != nullptr &&
|
storage_redirected.resources.images[0].image_id == depth_id &&
|
||||||
texture_cache.GetImage(depth_id).usage.storage,
|
storage_redirected.resources.images[0].image_view != nullptr &&
|
||||||
"storage stencil binding did not acquire the associated depth owner");
|
texture_cache.GetImage(depth_id).usage.storage,
|
||||||
|
"storage stencil binding did not acquire the associated depth owner");
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
resources.UnmapMemory(base, allocation_size, GpuAccess::ReadWrite);
|
resources.UnmapMemory(base, allocation_size, GpuAccess::ReadWrite);
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
@@ -6399,13 +6449,17 @@ public:
|
|||||||
const auto *buffers = Binding(Kind::Buffers);
|
const auto *buffers = Binding(Kind::Buffers);
|
||||||
if (buffers != nullptr) {
|
if (buffers != nullptr) {
|
||||||
buffer_infos.resize(buffers->resources.size());
|
buffer_infos.resize(buffers->resources.size());
|
||||||
for (auto &info : buffer_infos) {
|
for (u32 i = 0; i < buffer_infos.size(); i++) {
|
||||||
|
auto &info = buffer_infos[i];
|
||||||
info.buffer = buffer.buffer;
|
info.buffer = buffer.buffer;
|
||||||
info.offset = 0;
|
info.offset = 0;
|
||||||
info.range = buffer.size;
|
info.range = buffer.size;
|
||||||
if (test.storage_buffer_range_dwords != 0) {
|
if (test.storage_buffer_range_dwords != 0) {
|
||||||
|
const auto offset = i < test.storage_buffer_offsets.size()
|
||||||
|
? test.storage_buffer_offsets[i]
|
||||||
|
: 0u;
|
||||||
info.range = static_cast<vk::DeviceSize>(
|
info.range = static_cast<vk::DeviceSize>(
|
||||||
test.storage_buffer_range_dwords * sizeof(u32));
|
test.storage_buffer_range_dwords * sizeof(u32) + offset);
|
||||||
Require(test.name, "dispatch", info.range <= buffer.size,
|
Require(test.name, "dispatch", info.range <= buffer.size,
|
||||||
"storage buffer descriptor range exceeds backing buffer");
|
"storage buffer descriptor range exceeds backing buffer");
|
||||||
}
|
}
|
||||||
@@ -11731,6 +11785,58 @@ TestCase BufferStoreDwordIdxenUsesDescriptorStride() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase BufferStoreDwordAppliesHostOffset() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> code;
|
||||||
|
AppendVMovLiteral(&code, 0, 0xabcdef01u);
|
||||||
|
code.push_back(EncodeMubuf0(0x1cu, 0, false, false));
|
||||||
|
code.push_back(EncodeMubuf1(0, 0, 20));
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "BufferStoreDwordAppliesHostOffset";
|
||||||
|
test.code = code;
|
||||||
|
test.initial = {0x11111111u, 0x22222222u, 0x33333333u, 0};
|
||||||
|
test.expected = {0x11111111u, 0x22222222u, 0x33333333u, 0xabcdef01u};
|
||||||
|
test.storage_buffer_range_dwords = 1;
|
||||||
|
test.storage_buffer_offsets = {12};
|
||||||
|
test.opcodes = {O::VMovB32, O::BufferStoreDword, O::SEndpgm};
|
||||||
|
test.user_data = MakeStructuredStorageBufferData(4, 1);
|
||||||
|
test.has_user_data = true;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCase BufferOffsetsUsePackedLaneAndStorageFallback() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> code;
|
||||||
|
for (u32 base : {0u, 4u}) {
|
||||||
|
AppendSMovLiteral(&code, base, 0x1000u + base * 0x1000u);
|
||||||
|
AppendSMovLiteral(&code, base + 1u, 4u << 16u);
|
||||||
|
AppendSMovLiteral(&code, base + 2u, 1u);
|
||||||
|
AppendSMovLiteral(&code, base + 3u, 1u << 24u);
|
||||||
|
}
|
||||||
|
AppendVMovLiteral(&code, 0, 0x12345678u);
|
||||||
|
code.push_back(EncodeMubuf0(0x1cu, 0, false, false));
|
||||||
|
code.push_back(EncodeMubuf1(0, 0, 20));
|
||||||
|
AppendVMovLiteral(&code, 1, 0xabcdef01u);
|
||||||
|
code.push_back(EncodeMubuf0(0x1cu, 0, false, false));
|
||||||
|
code.push_back(EncodeMubuf1(1, 1, 20));
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "BufferOffsetsUsePackedLaneAndStorageFallback";
|
||||||
|
test.code = std::move(code);
|
||||||
|
test.initial = {0, 0, 0, 0};
|
||||||
|
test.expected = {0x12345678u, 0, 0, 0xabcdef01u};
|
||||||
|
test.storage_buffer_range_dwords = 1;
|
||||||
|
test.storage_buffer_offsets = {0, 12};
|
||||||
|
test.force_shader_data_storage = true;
|
||||||
|
test.opcodes = {O::SMovB32, O::VMovB32, O::BufferStoreDword, O::SEndpgm};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase BufferLoadVariants() {
|
TestCase BufferLoadVariants() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -14359,6 +14465,8 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(BufferLoadDwordNoAddressFlagsIgnoresVaddr);
|
AddCase(BufferLoadDwordNoAddressFlagsIgnoresVaddr);
|
||||||
AddCase(BufferLoadDwordIdxenUsesDescriptorStride);
|
AddCase(BufferLoadDwordIdxenUsesDescriptorStride);
|
||||||
AddCase(BufferStoreDwordIdxenUsesDescriptorStride);
|
AddCase(BufferStoreDwordIdxenUsesDescriptorStride);
|
||||||
|
AddCase(BufferStoreDwordAppliesHostOffset);
|
||||||
|
AddCase(BufferOffsetsUsePackedLaneAndStorageFallback);
|
||||||
AddCase(BufferLoadVariants);
|
AddCase(BufferLoadVariants);
|
||||||
AddCase(BufferStoreVariants);
|
AddCase(BufferStoreVariants);
|
||||||
AddCase(BufferFormatVariants);
|
AddCase(BufferFormatVariants);
|
||||||
@@ -14730,8 +14838,7 @@ void CheckReverseRenderTargetFormatContract() {
|
|||||||
vk::Format::eR8G8B8A8Unorm,
|
vk::Format::eR8G8B8A8Unorm,
|
||||||
DstSel(4, 5, 6, 2));
|
DstSel(4, 5, 6, 2));
|
||||||
} else if (std::strcmp(kind, "sampled-incompatible-format") == 0) {
|
} else if (std::strcmp(kind, "sampled-incompatible-format") == 0) {
|
||||||
(void)SelectSampledColorView(vk::Format::eR8Unorm,
|
(void)SelectSampledColorView(vk::Format::eR8Unorm, vk::Format::eR16Unorm,
|
||||||
vk::Format::eR16Unorm,
|
|
||||||
DstSel(4, 0, 0, 1));
|
DstSel(4, 0, 0, 1));
|
||||||
} else if (std::strcmp(kind, "sampled-invalid-high") == 0) {
|
} else if (std::strcmp(kind, "sampled-invalid-high") == 0) {
|
||||||
(void)SelectSampledColorView(vk::Format::eR8G8B8A8Unorm,
|
(void)SelectSampledColorView(vk::Format::eR8G8B8A8Unorm,
|
||||||
@@ -14831,8 +14938,7 @@ void CheckSampledColorViews() {
|
|||||||
valid_swizzles += valid;
|
valid_swizzles += valid;
|
||||||
}
|
}
|
||||||
Require("SampledColorViews", "all PS5 read swizzles",
|
Require("SampledColorViews", "all PS5 read swizzles",
|
||||||
valid_swizzles == 1296 &&
|
valid_swizzles == 1296 && !IsValidImageSwizzle(DstSel(4, 5, 6, 2)) &&
|
||||||
!IsValidImageSwizzle(DstSel(4, 5, 6, 2)) &&
|
|
||||||
!IsValidImageSwizzle(DstSel(4, 5, 6, 3)) &&
|
!IsValidImageSwizzle(DstSel(4, 5, 6, 3)) &&
|
||||||
!IsValidImageSwizzle(0x1000),
|
!IsValidImageSwizzle(0x1000),
|
||||||
"valid PS5 sampled mappings were rejected or reserved selectors were "
|
"valid PS5 sampled mappings were rejected or reserved selectors were "
|
||||||
@@ -14857,8 +14963,7 @@ void CheckSampledColorViews() {
|
|||||||
DstSel(0, 0, 0, 4)) == DstSel(0, 0, 0, 4),
|
DstSel(0, 0, 0, 4)) == DstSel(0, 0, 0, 4),
|
||||||
"R8 did not select its 000R component-mapped view");
|
"R8 did not select its 000R component-mapped view");
|
||||||
Require("SampledColorViews", "mutable R8 uint/unorm 000R",
|
Require("SampledColorViews", "mutable R8 uint/unorm 000R",
|
||||||
SelectSampledColorView(vk::Format::eR8Uint,
|
SelectSampledColorView(vk::Format::eR8Uint, vk::Format::eR8Unorm,
|
||||||
vk::Format::eR8Unorm,
|
|
||||||
DstSel(0, 0, 0, 4)) == DstSel(0, 0, 0, 4),
|
DstSel(0, 0, 0, 4)) == DstSel(0, 0, 0, 4),
|
||||||
"compatible R8 integer target sampled view was rejected");
|
"compatible R8 integer target sampled view was rejected");
|
||||||
Require("SampledColorViews", "R16G16 RG01",
|
Require("SampledColorViews", "R16G16 RG01",
|
||||||
@@ -15486,9 +15591,9 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) {
|
|||||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
|
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
|
||||||
cube_resource.read = true;
|
cube_resource.read = true;
|
||||||
cube_resource.depth_compare = true;
|
cube_resource.depth_compare = true;
|
||||||
const auto cube_view = ResolveTargetTextureView(
|
const auto cube_view =
|
||||||
cube_resource, Prospero::ImageType::kCube, 0,
|
ResolveTargetTextureView(cube_resource, Prospero::ImageType::kCube, 0,
|
||||||
cube_image.info.resources.layers);
|
cube_image.info.resources.layers);
|
||||||
Require("SampledDepthDescriptor", "normalized depth cube",
|
Require("SampledDepthDescriptor", "normalized depth cube",
|
||||||
IsSupportedDepthTargetDescriptor(cube_descriptor, cube_image) &&
|
IsSupportedDepthTargetDescriptor(cube_descriptor, cube_image) &&
|
||||||
IsSupportedDepthTextureEncoding(cube_descriptor) &&
|
IsSupportedDepthTextureEncoding(cube_descriptor) &&
|
||||||
@@ -15741,9 +15846,9 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
"basic 3D storage descriptor fixture is malformed");
|
"basic 3D storage descriptor fixture is malformed");
|
||||||
ValidateStorageTexture(BasicStorageTextureResource(), descriptor, 0x10000);
|
ValidateStorageTexture(BasicStorageTextureResource(), descriptor, 0x10000);
|
||||||
|
|
||||||
const ShaderTextureResource extended{{
|
const ShaderTextureResource extended{{0x204aca00u, 0xc4700000u, 0x000fc00fu,
|
||||||
0x204aca00u, 0xc4700000u, 0x000fc00fu, 0xa1b00facu,
|
0xa1b00facu, 0x0000003fu, 0x00700000u,
|
||||||
0x0000003fu, 0x00700000u, 0x006b0000u, 0x00204b0au}};
|
0x006b0000u, 0x00204b0au}};
|
||||||
auto extended_resource = BasicStorageTextureResource();
|
auto extended_resource = BasicStorageTextureResource();
|
||||||
extended_resource.read = false;
|
extended_resource.read = false;
|
||||||
Require("BasicStorageTexture", "extended descriptor",
|
Require("BasicStorageTexture", "extended descriptor",
|
||||||
@@ -15776,18 +15881,17 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), bgra, 0x870000);
|
ValidateStorageTexture(BasicBgraStorageTextureResource(), bgra, 0x870000);
|
||||||
|
|
||||||
const auto r11g11b10 = Ppsa06228R11G11B10StorageTextureDescriptor();
|
const auto r11g11b10 = Ppsa06228R11G11B10StorageTextureDescriptor();
|
||||||
Require("BasicStorageTexture", "PPSA06228 R11G11B10 descriptor",
|
Require(
|
||||||
r11g11b10.Base40() == 0x10c6b50000ull &&
|
"BasicStorageTexture", "PPSA06228 R11G11B10 descriptor",
|
||||||
r11g11b10.Width5() + 1u == 1920 &&
|
r11g11b10.Base40() == 0x10c6b50000ull &&
|
||||||
r11g11b10.Height5() + 1u == 1080 &&
|
r11g11b10.Width5() + 1u == 1920 && r11g11b10.Height5() + 1u == 1080 &&
|
||||||
r11g11b10.Depth() + 1u == 1 &&
|
r11g11b10.Depth() + 1u == 1 &&
|
||||||
r11g11b10.Format() ==
|
r11g11b10.Format() ==
|
||||||
Prospero::GpuEnumValue(
|
Prospero::GpuEnumValue(Prospero::BufferFormat::k11_11_10Float) &&
|
||||||
Prospero::BufferFormat::k11_11_10Float) &&
|
r11g11b10.TileMode() ==
|
||||||
r11g11b10.TileMode() ==
|
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||||
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
r11g11b10.DstSelXYZW() == DstSel(4, 5, 6, 1),
|
||||||
r11g11b10.DstSelXYZW() == DstSel(4, 5, 6, 1),
|
"PPSA06228 R11G11B10 storage descriptor fixture is malformed");
|
||||||
"PPSA06228 R11G11B10 storage descriptor fixture is malformed");
|
|
||||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), r11g11b10,
|
ValidateStorageTexture(BasicBgraStorageTextureResource(), r11g11b10,
|
||||||
0x870000);
|
0x870000);
|
||||||
ValidateStorageColorView(vk::Format::eB10G11R11UfloatPack32,
|
ValidateStorageColorView(vk::Format::eB10G11R11UfloatPack32,
|
||||||
@@ -15878,8 +15982,7 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
if (!IsValidImageSwizzle(swizzle)) {
|
if (!IsValidImageSwizzle(swizzle)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
all_swizzles.fields[3] =
|
all_swizzles.fields[3] = (all_swizzles.fields[3] & ~0xfffu) | swizzle;
|
||||||
(all_swizzles.fields[3] & ~0xfffu) | swizzle;
|
|
||||||
ValidateStorageTexture(BasicLinearStorageTextureResource(), all_swizzles,
|
ValidateStorageTexture(BasicLinearStorageTextureResource(), all_swizzles,
|
||||||
0x800);
|
0x800);
|
||||||
ValidateStorageColorView(vk::Format::eR16G16B16A16Sfloat,
|
ValidateStorageColorView(vk::Format::eR16G16B16A16Sfloat,
|
||||||
@@ -15921,15 +16024,13 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
ValidateStorageTexture(BasicUintArrayStorageTextureResource(), uint_array,
|
ValidateStorageTexture(BasicUintArrayStorageTextureResource(), uint_array,
|
||||||
0x10000);
|
0x10000);
|
||||||
|
|
||||||
const auto standard4kb_array =
|
const auto standard4kb_array = Standard4KBUintArrayStorageTextureDescriptor();
|
||||||
Standard4KBUintArrayStorageTextureDescriptor();
|
|
||||||
const auto standard4kb_pitch = TileGetTexturePitch(
|
const auto standard4kb_pitch = TileGetTexturePitch(
|
||||||
standard4kb_array.Format(), 1, 1, standard4kb_array.TileMode());
|
standard4kb_array.Format(), 1, 1, standard4kb_array.TileMode());
|
||||||
TileSizeAlign standard4kb_size{};
|
TileSizeAlign standard4kb_size{};
|
||||||
TileGetTextureTotalSize(standard4kb_array.Format(), 1, 1, 1,
|
TileGetTextureTotalSize(standard4kb_array.Format(), 1, 1, 1,
|
||||||
standard4kb_pitch, 1,
|
standard4kb_pitch, 1, standard4kb_array.TileMode(),
|
||||||
standard4kb_array.TileMode(), false,
|
false, standard4kb_size);
|
||||||
standard4kb_size);
|
|
||||||
Require("BasicStorageTexture", "Standard4KB uint 2D-array descriptor",
|
Require("BasicStorageTexture", "Standard4KB uint 2D-array descriptor",
|
||||||
standard4kb_array.Type() ==
|
standard4kb_array.Type() ==
|
||||||
Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) &&
|
Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) &&
|
||||||
@@ -15947,9 +16048,9 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
auto based_standard4kb_array = standard4kb_array;
|
auto based_standard4kb_array = standard4kb_array;
|
||||||
based_standard4kb_array.fields[0] = 0x006c6800u;
|
based_standard4kb_array.fields[0] = 0x006c6800u;
|
||||||
based_standard4kb_array.fields[4] = 0x00010001u;
|
based_standard4kb_array.fields[4] = 0x00010001u;
|
||||||
const auto based_standard4kb_pitch = TileGetTexturePitch(
|
const auto based_standard4kb_pitch =
|
||||||
based_standard4kb_array.Format(), 1, 1,
|
TileGetTexturePitch(based_standard4kb_array.Format(), 1, 1,
|
||||||
based_standard4kb_array.TileMode());
|
based_standard4kb_array.TileMode());
|
||||||
TileSizeAlign based_standard4kb_size{};
|
TileSizeAlign based_standard4kb_size{};
|
||||||
TileGetTextureTotalSize(
|
TileGetTextureTotalSize(
|
||||||
based_standard4kb_array.Format(), 1, 1,
|
based_standard4kb_array.Format(), 1, 1,
|
||||||
@@ -15963,8 +16064,7 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
based_standard4kb_size.align == 0x1000,
|
based_standard4kb_size.align == 0x1000,
|
||||||
"captured based Standard4KB array view is malformed");
|
"captured based Standard4KB array view is malformed");
|
||||||
ValidateStorageTexture(BasicUintArrayStorageTextureResource(),
|
ValidateStorageTexture(BasicUintArrayStorageTextureResource(),
|
||||||
based_standard4kb_array,
|
based_standard4kb_array, based_standard4kb_size.size);
|
||||||
based_standard4kb_size.size);
|
|
||||||
|
|
||||||
const auto uint_volume = BasicUintVolumeStorageTextureDescriptor();
|
const auto uint_volume = BasicUintVolumeStorageTextureDescriptor();
|
||||||
Require("BasicStorageTexture", "uint 3D descriptor",
|
Require("BasicStorageTexture", "uint 3D descriptor",
|
||||||
@@ -15983,9 +16083,9 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
ValidateStorageTexture(BasicUintVolumeStorageTextureResource(), uint_volume,
|
ValidateStorageTexture(BasicUintVolumeStorageTextureResource(), uint_volume,
|
||||||
0x10000);
|
0x10000);
|
||||||
|
|
||||||
const ShaderTextureResource tiled_uint_volume{{
|
const ShaderTextureResource tiled_uint_volume{
|
||||||
0x1ac0e530u, 0xc0b00000u, 0x0003c003u, 0xa0500004u,
|
{0x1ac0e530u, 0xc0b00000u, 0x0003c003u, 0xa0500004u, 0x0000000fu,
|
||||||
0x0000000fu, 0x00700000u, 0x00000000u, 0x00000000u}};
|
0x00700000u, 0x00000000u, 0x00000000u}};
|
||||||
Require("BasicStorageTexture", "tiled uint 3D descriptor",
|
Require("BasicStorageTexture", "tiled uint 3D descriptor",
|
||||||
tiled_uint_volume.Width5() + 1u == 16 &&
|
tiled_uint_volume.Width5() + 1u == 16 &&
|
||||||
tiled_uint_volume.Height5() + 1u == 16 &&
|
tiled_uint_volume.Height5() + 1u == 16 &&
|
||||||
@@ -16028,14 +16128,14 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
Prospero::GpuEnumValue(Prospero::TileMode::kDepth) &&
|
Prospero::GpuEnumValue(Prospero::TileMode::kDepth) &&
|
||||||
d16_depth_tile.DstSelXYZW() == DstSel(4, 0, 0, 1),
|
d16_depth_tile.DstSelXYZW() == DstSel(4, 0, 0, 1),
|
||||||
"PPSA10112 writable D16 depth-plane descriptor fixture is malformed");
|
"PPSA10112 writable D16 depth-plane descriptor fixture is malformed");
|
||||||
const auto d16_pitch = TileGetTexturePitch(
|
const auto d16_pitch =
|
||||||
d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u, 1,
|
TileGetTexturePitch(d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u,
|
||||||
d16_depth_tile.TileMode());
|
1, d16_depth_tile.TileMode());
|
||||||
TileSizeAlign d16_size{};
|
TileSizeAlign d16_size{};
|
||||||
TileGetTextureTotalSize(
|
TileGetTextureTotalSize(d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u,
|
||||||
d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u,
|
d16_depth_tile.Height5() + 1u,
|
||||||
d16_depth_tile.Height5() + 1u, d16_depth_tile.Depth() + 1u, d16_pitch, 1,
|
d16_depth_tile.Depth() + 1u, d16_pitch, 1,
|
||||||
d16_depth_tile.TileMode(), false, d16_size);
|
d16_depth_tile.TileMode(), false, d16_size);
|
||||||
Require("BasicStorageTexture", "PPSA10112 D16 depth-tile footprint",
|
Require("BasicStorageTexture", "PPSA10112 D16 depth-tile footprint",
|
||||||
d16_pitch == 256 && d16_size.size == 0x20000 &&
|
d16_pitch == 256 && d16_size.size == 0x20000 &&
|
||||||
d16_size.align == 0x10000,
|
d16_size.align == 0x10000,
|
||||||
@@ -16064,8 +16164,8 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
for (const char *kind :
|
for (const char *kind :
|
||||||
{"resource", "type", "tile", "mip", "swizzle", "linear-rgb1-read",
|
{"resource", "type", "tile", "mip", "swizzle", "linear-rgb1-read",
|
||||||
"bgra-read", "r16-float-read", "r8-unorm-read", "yzwx-read",
|
"bgra-read", "r16-float-read", "r8-unorm-read", "yzwx-read",
|
||||||
"reserved-swizzle", "array-base-out-of-range", "array-mip-view", "reserved",
|
"reserved-swizzle", "array-base-out-of-range", "array-mip-view",
|
||||||
"uint-format", "uint-resource-float-format",
|
"reserved", "uint-format", "uint-resource-float-format",
|
||||||
"depth-tile-read", "depth-tile-extent", "depth-tile-fmask"}) {
|
"depth-tile-read", "depth-tile-extent", "depth-tile-fmask"}) {
|
||||||
std::string command = std::string("\"") + path +
|
std::string command = std::string("\"") + path +
|
||||||
"\" --storage-texture-descriptor-death " + kind;
|
"\" --storage-texture-descriptor-death " + kind;
|
||||||
@@ -16484,6 +16584,38 @@ void CheckDepthHtileStencilCompatibility() {
|
|||||||
std::printf("[host] %-32s ok\n", "DepthHtileStencilCompatibility");
|
std::printf("[host] %-32s ok\n", "DepthHtileStencilCompatibility");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckPs5DepthRegisterDecoding() {
|
||||||
|
constexpr uint32_t captured_z = 0x22900803u;
|
||||||
|
constexpr uint32_t captured_stencil = 0x00100801u;
|
||||||
|
const auto z = HW::DepthZInfo::Decode(captured_z);
|
||||||
|
const auto stencil = HW::DepthStencilInfo::Decode(captured_stencil);
|
||||||
|
Require(
|
||||||
|
"Ps5DepthRegisterDecoding", "captured texture-compatible state",
|
||||||
|
z.format == Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F) &&
|
||||||
|
z.num_samples == 0 && z.htile_acceleration && !z.expclear_enabled &&
|
||||||
|
!z.partially_resident && z.max_mip_level == 0 &&
|
||||||
|
z.z_compare_base == Prospero::ZCompareBase::kZMin &&
|
||||||
|
z.texture_compatibility ==
|
||||||
|
Prospero::TextureCompatiblePlaneCompression::kEnable &&
|
||||||
|
z.HasValidTextureCompatibility() &&
|
||||||
|
stencil.format ==
|
||||||
|
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt) &&
|
||||||
|
!stencil.htile_stencil_disabled && !stencil.expclear_enabled &&
|
||||||
|
!stencil.partially_resident &&
|
||||||
|
stencil.texture_compatibility ==
|
||||||
|
Prospero::TextureCompatibleStencil::kEnable &&
|
||||||
|
stencil.HasValidTextureCompatibility(),
|
||||||
|
"valid PS5 depth/stencil aggregate encodings were not decoded exactly");
|
||||||
|
|
||||||
|
const auto malformed_z = HW::DepthZInfo::Decode(0x00000803u);
|
||||||
|
const auto malformed_stencil = HW::DepthStencilInfo::Decode(0x00100001u);
|
||||||
|
Require("Ps5DepthRegisterDecoding", "malformed aggregate state",
|
||||||
|
!malformed_z.HasValidTextureCompatibility() &&
|
||||||
|
!malformed_stencil.HasValidTextureCompatibility(),
|
||||||
|
"partial texture-compatible aggregate encodings were accepted");
|
||||||
|
std::printf("[host] %-32s ok\n", "Ps5DepthRegisterDecoding");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStencilAttachmentAccess() {
|
void CheckStencilAttachmentAccess() {
|
||||||
PipelineStencilStaticState state{vk::StencilOp::eKeep, vk::StencilOp::eKeep,
|
PipelineStencilStaticState state{vk::StencilOp::eKeep, vk::StencilOp::eKeep,
|
||||||
vk::StencilOp::eKeep,
|
vk::StencilOp::eKeep,
|
||||||
@@ -17023,6 +17155,24 @@ void CheckPm4AcquireMemNoOp(RenderContext &renderer) {
|
|||||||
std::printf("[host] %-32s ok\n", "Pm4AcquireMemNoOp");
|
std::printf("[host] %-32s ok\n", "Pm4AcquireMemNoOp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckPm4StencilInfoValueLane(RenderContext &renderer) {
|
||||||
|
CommandProcessor processor(renderer);
|
||||||
|
constexpr std::array<uint32_t, 2> payload{0x00100801u, 0x28000000u};
|
||||||
|
const auto consumed =
|
||||||
|
HwCtxSetStencilInfo(processor, 0xC0016900u, Pm4::DB_STENCIL_INFO,
|
||||||
|
payload.data(), 1);
|
||||||
|
const auto &stencil = processor.GetCtx().GetDepthStencilInfo();
|
||||||
|
Require(
|
||||||
|
"Pm4StencilInfoValueLane", "standalone register value", consumed == 1 &&
|
||||||
|
stencil.format ==
|
||||||
|
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt) &&
|
||||||
|
stencil.texture_compatibility ==
|
||||||
|
Prospero::TextureCompatibleStencil::kEnable &&
|
||||||
|
!stencil.expclear_enabled && !stencil.htile_stencil_disabled,
|
||||||
|
"standalone DB_STENCIL_INFO did not decode its sole payload value");
|
||||||
|
std::printf("[host] %-32s ok\n", "Pm4StencilInfoValueLane");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckPm4WaitResume(RenderContext &renderer) {
|
void CheckPm4WaitResume(RenderContext &renderer) {
|
||||||
GraphicsInitJmpTables();
|
GraphicsInitJmpTables();
|
||||||
CommandProcessor processor(renderer);
|
CommandProcessor processor(renderer);
|
||||||
@@ -17272,6 +17422,7 @@ int main(int argc, char **argv) {
|
|||||||
CheckStorageTextureVolumeMipRegions();
|
CheckStorageTextureVolumeMipRegions();
|
||||||
CheckStorageTextureGpuOwnedRebindState();
|
CheckStorageTextureGpuOwnedRebindState();
|
||||||
CheckNativeMsaaState();
|
CheckNativeMsaaState();
|
||||||
|
CheckPs5DepthRegisterDecoding();
|
||||||
CheckDepthHtileStencilCompatibility();
|
CheckDepthHtileStencilCompatibility();
|
||||||
CheckStencilAttachmentAccess();
|
CheckStencilAttachmentAccess();
|
||||||
CheckDepthAttachmentWrites();
|
CheckDepthAttachmentWrites();
|
||||||
@@ -17289,6 +17440,7 @@ int main(int argc, char **argv) {
|
|||||||
CheckReferenceClockScale();
|
CheckReferenceClockScale();
|
||||||
CheckVulkan13FeatureRequirements();
|
CheckVulkan13FeatureRequirements();
|
||||||
CheckPm4AcquireMemNoOp(vulkan.RuntimeRenderer());
|
CheckPm4AcquireMemNoOp(vulkan.RuntimeRenderer());
|
||||||
|
CheckPm4StencilInfoValueLane(vulkan.RuntimeRenderer());
|
||||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||||
CheckPm4CeCompletion(vulkan.RuntimeRenderer());
|
CheckPm4CeCompletion(vulkan.RuntimeRenderer());
|
||||||
CheckEmbeddedFetchVertexOffset();
|
CheckEmbeddedFetchVertexOffset();
|
||||||
|
|||||||
Reference in New Issue
Block a user