graphics: unify buffer bindings and depth target handling

This commit is contained in:
nmzik
2026-07-27 10:08:08 +02:00
parent f43567e12c
commit 142b3c20fa
17 changed files with 669 additions and 564 deletions
+21 -83
View File
@@ -430,21 +430,17 @@ static void ZPrint(const char* func, const HW::DepthRenderTarget& z) {
LOGF("%s\n", func);
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.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.zrange_precision = 0x%08" PRIx32 "\n"
"\t z_info.embedded_sample_locations = %s\n"
"\t z_info.z_compare_base = 0x%08" PRIx32 "\n"
"\t z_info.partially_resident = %s\n"
"\t z_info.num_mip_levels = 0x%02" PRIx8 "\n"
"\t z_info.plane_compression = 0x%02" PRIx8 "\n"
"\t z_info.max_mip_level = 0x%02" PRIx8 "\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.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 depth_info.addr5_swizzle_mask = 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 size.x_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.tile_surface_enable ? "true" : "false",
z.z_info.expclear_enabled ? "true" : "false", z.z_info.zrange_precision,
z.z_info.embedded_sample_locations ? "true" : "false",
z.z_info.partially_resident ? "true" : "false", z.z_info.num_mip_levels,
z.z_info.plane_compression, z.stencil_info.format,
z.stencil_info.tile_stencil_disable ? "true" : "false",
z.stencil_info.expclear_enabled ? "true" : "false", z.stencil_info.tile_mode_index,
z.stencil_info.tile_split, z.stencil_info.texture_compatible_stencil ? "true" : "false",
z.z_info.format, z.z_info.num_samples,
Prospero::GpuEnumValue(z.z_info.texture_compatibility),
z.z_info.htile_acceleration ? "true" : "false",
z.z_info.expclear_enabled ? "true" : "false",
Prospero::GpuEnumValue(z.z_info.z_compare_base),
z.z_info.partially_resident ? "true" : "false", z.z_info.max_mip_level,
z.stencil_info.format, Prospero::GpuEnumValue(z.stencil_info.texture_compatibility),
z.stencil_info.htile_stencil_disabled ? "true" : "false",
z.stencil_info.expclear_enabled ? "true" : "false",
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.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)
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) {
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.tile_surface_enable != false);
EXIT_NOT_IMPLEMENTED(z.z_info.htile_acceleration != 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.num_mip_levels != 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;
}
}
EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 0);
} else {
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) {
static bool logged = false;
if (!logged) {
@@ -540,56 +517,17 @@ static void ZCheck(const HW::DepthRenderTarget& z) {
logged = true;
}
}
// EXIT_NOT_IMPLEMENTED(z.z_info.tile_surface_enable != true);
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.num_mip_levels != 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;
}
}
EXIT_NOT_IMPLEMENTED(z.z_info.max_mip_level != 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.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);
} else {
// 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.format != 0x00000001);
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);
}
@@ -87,7 +87,7 @@ static bool UsesStencilOpValue(uint8_t fail, uint8_t pass, uint8_t depth_fail) {
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandBuffer& buffer,
RenderDepthInfo& r) {
RenderDepthInfo& r) {
KYTY_PROFILER_FUNCTION();
(void)submit_id;
const auto& hw = buffer.GetRegisters();
@@ -102,31 +102,34 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
if (!depth_active && !stencil_active) {
return;
}
if (!z.z_info.HasValidTextureCompatibility() ||
!z.stencil_info.HasValidTextureCompatibility()) {
DepthFatal("invalid PS5 depth texture-compatibility encoding");
}
const bool attachment_unbound =
z.z_info.format == Prospero::GpuEnumValue(Prospero::DepthFormat::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.zrange_precision <= 1 && !z.z_info.expclear_enabled &&
!z.z_info.embedded_sample_locations && !z.z_info.partially_resident &&
z.z_info.num_mip_levels == 0 && z.z_info.plane_compression == 0 &&
z.stencil_info.tile_mode_index == 0 && z.stencil_info.tile_split == 0 &&
!z.stencil_info.expclear_enabled && !z.stencil_info.texture_compatible_stencil &&
!z.stencil_info.partially_resident && z.depth_view.slice_start == 0 &&
z.depth_view.slice_max == 0 && z.depth_view.current_mip_level == 0 &&
!z.depth_view.depth_write_disable && !z.depth_view.stencil_write_disable &&
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.bank_height == 0 && z.depth_info.macro_tile_aspect == 0 &&
z.depth_info.num_banks == 0 && z.htile_surface.linear == 0 &&
z.htile_surface.full_cache == 0 && z.htile_surface.htile_uses_preload_win == 0 &&
z.htile_surface.preload == 0 && z.htile_surface.prefetch_width == 0 &&
z.htile_surface.prefetch_height == 0 && z.htile_surface.dst_outside_zero_to_one == 0 &&
z.z_read_base_addr == 0 && z.z_write_base_addr == 0 && z.stencil_read_base_addr == 0 &&
z.z_info.num_samples == 0 &&
z.z_info.texture_compatibility == Prospero::TextureCompatiblePlaneCompression::kDisable &&
!z.z_info.expclear_enabled && !z.z_info.partially_resident && z.z_info.max_mip_level == 0 &&
z.stencil_info.texture_compatibility == Prospero::TextureCompatibleStencil::kDisable &&
!z.stencil_info.expclear_enabled && !z.stencil_info.partially_resident &&
z.depth_view.slice_start == 0 && z.depth_view.slice_max == 0 &&
z.depth_view.current_mip_level == 0 && !z.depth_view.depth_write_disable &&
!z.depth_view.stencil_write_disable && 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.bank_height == 0 &&
z.depth_info.macro_tile_aspect == 0 && z.depth_info.num_banks == 0 &&
z.htile_surface.linear == 0 && z.htile_surface.full_cache == 0 &&
z.htile_surface.htile_uses_preload_win == 0 && z.htile_surface.preload == 0 &&
z.htile_surface.prefetch_width == 0 && z.htile_surface.prefetch_height == 0 &&
z.htile_surface.dst_outside_zero_to_one == 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 &&
// 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
// 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.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 && z.width == 0 && z.height == 0;
if (attachment_unbound) {
@@ -138,13 +141,13 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
}
const bool has_stencil =
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);
if (samples == 0) {
DepthFatal("unsupported depth fragment count: %u", z.z_info.num_samples);
}
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);
switch (view.type) {
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,
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 ||
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.stencil_info.partially_resident || z.z_info.plane_compression != 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.z_info.partially_resident || z.stencil_info.partially_resident ||
z.z_info.max_mip_level != 0 || z.depth_view.current_mip_level != 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.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");
}
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) ||
z.stencil_info.tile_mode_index != 0 || z.stencil_info.tile_split != 0 ||
!htile_stencil_compat || z.stencil_info.texture_compatible_stencil ||
z.stencil_read_base_addr == 0 ||
!htile_stencil_compat || z.stencil_read_base_addr == 0 ||
z.stencil_write_base_addr != z.stencil_read_base_addr ||
(z.stencil_read_base_addr & 0xffffu) != 0 || z.depth_view.stencil_write_disable) {
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 ||
z.stencil_info.tile_mode_index != 0 || z.stencil_info.tile_split != 0 ||
!htile_stencil_compat || z.stencil_info.texture_compatible_stencil) {
!htile_stencil_compat ||
z.stencil_info.texture_compatibility !=
Prospero::TextureCompatibleStencil::kDisable) {
DepthFatal("stencil state without an active stencil attachment");
}
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)) {
DepthFatal("layered depth backing range is invalid");
}
r.htile = has_htile;
r.width = width;
r.height = height;
r.samples = samples;
r.depth_buffer_size = depth_backing_size;
r.depth_buffer_vaddr = z.z_read_base_addr;
r.stencil_buffer_size = has_stencil ? stencil_backing_size : 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_vaddr = has_htile ? z.htile_data_base_addr : 0;
r.htile = has_htile;
r.width = width;
r.height = height;
r.samples = samples;
r.depth_buffer_size = depth_backing_size;
r.depth_buffer_vaddr = z.z_read_base_addr;
r.stencil_buffer_size = has_stencil ? stencil_backing_size : 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_vaddr = has_htile ? z.htile_data_base_addr : 0;
r.depth_clear_enable = rc.depth_clear_enable;
r.depth_meta_clear_enable = false;
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;
}
TextureCache::ImageDesc desc {};
desc.type = TextureCache::BindingType::DepthTarget;
desc.info.data = {r.depth_buffer_vaddr, r.depth_buffer_size};
desc.info.stencil = {r.stencil_buffer_vaddr, r.stencil_buffer_size};
desc.info.pixel_format = r.format;
desc.info.guest_format = guest_format;
desc.info.type = Prospero::ImageType::kColor2D;
desc.info.extent = {width, height, 1};
desc.type = TextureCache::BindingType::DepthTarget;
desc.info.data = {r.depth_buffer_vaddr, r.depth_buffer_size};
desc.info.stencil = {r.stencil_buffer_vaddr, r.stencil_buffer_size};
desc.info.pixel_format = r.format;
desc.info.guest_format = guest_format;
desc.info.type = Prospero::ImageType::kColor2D;
desc.info.extent = {width, height, 1};
desc.info.resources = {1, view.image_layers};
desc.info.pitch = pitch;
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.kind = has_htile ? ImageMetadataKind::Htile : ImageMetadataKind::None;
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.type =
view.layer_count == 1 ? vk::ImageViewType::e2D : vk::ImageViewType::e2DArray;
desc.view_info.aspect = ImageViewOps::DepthAspectMask(r.format);
desc.view_info.base_level = 0;
desc.view_info.level_count = 1;
desc.view_info.base_layer = view.base_layer;
desc.view_info.layer_count = view.layer_count;
desc.view_info.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment;
r.desc = std::move(desc);
auto& cache = m_context.GetTextureCache();
r.image_id = cache.FindImage(r.desc);
r.image_view = nullptr;
desc.view_info.aspect = ImageViewOps::DepthAspectMask(r.format);
desc.view_info.base_level = 0;
desc.view_info.level_count = 1;
desc.view_info.base_layer = view.base_layer;
desc.view_info.layer_count = view.layer_count;
desc.view_info.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment;
r.desc = std::move(desc);
auto& cache = m_context.GetTextureCache();
r.image_id = cache.FindImage(r.desc);
r.image_view = nullptr;
BindRenderTarget(r.image_id);
}
@@ -372,7 +360,7 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const {
return {};
}
const auto available = ImageViewOps::DepthAspectMask(format);
const auto available = ImageViewOps::DepthAspectMask(format);
vk::ImageAspectFlags writes {};
if ((available & vk::ImageAspectFlagBits::eDepth) &&
(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);
};
if (stencil_clear_enable ||
(stencil_test_enable &&
(face_writes(stencil_static_front, stencil_dynamic_front) ||
face_writes(stencil_static_back, stencil_dynamic_back)))) {
(stencil_test_enable && (face_writes(stencil_static_front, stencil_dynamic_front) ||
face_writes(stencil_static_back, stencil_dynamic_back)))) {
writes |= vk::ImageAspectFlagBits::eStencil;
}
return writes;
@@ -14,12 +14,12 @@ namespace Libs::Graphics {
class RenderCommandBuffer;
inline constexpr bool depth_htile_stencil_acceleration_compatible(bool has_stencil, bool has_htile,
bool acceleration_disabled) {
return acceleration_disabled || (has_stencil && has_htile);
bool htile_stencil_disabled) {
return htile_stencil_disabled || (has_stencil && has_htile);
}
struct RenderDepthInfo {
TextureCache::ImageDesc desc;
TextureCache::ImageDesc desc;
vk::Format format = vk::Format::eUndefined;
uint32_t width = 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) {
const auto available = ImageViewOps::DepthAspectMask(depth.format);
const auto writes = depth.AttachmentWriteAspects();
const bool has_depth = static_cast<bool>(available & vk::ImageAspectFlagBits::eDepth);
const bool has_stencil = static_cast<bool>(available & vk::ImageAspectFlagBits::eStencil);
const bool depth_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eDepth);
const auto available = ImageViewOps::DepthAspectMask(depth.format);
const auto writes = depth.AttachmentWriteAspects();
const bool has_depth = static_cast<bool>(available & vk::ImageAspectFlagBits::eDepth);
const bool has_stencil = static_cast<bool>(available & vk::ImageAspectFlagBits::eStencil);
const bool depth_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eDepth);
const bool stencil_write = static_cast<bool>(writes & vk::ImageAspectFlagBits::eStencil);
if (!has_stencil) {
return depth_write ? vk::ImageLayout::eDepthAttachmentOptimal
+100 -109
View File
@@ -73,11 +73,12 @@ static Prospero::ImageType TextureBaseType(Prospero::ImageType type) {
}
}
static BufferView NativeStorageBuffer(RenderContext& context,
CommandBuffer& command_buffer,
static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& command_buffer,
const ShaderBufferResource& descriptor,
const ShaderRecompiler::IR::BufferResource& resource) {
const ShaderRecompiler::IR::BufferResource& resource,
uint32_t& buffer_offset) {
BufferView result;
buffer_offset = 0;
const auto address = descriptor.Base48();
const auto stride = descriptor.Stride();
@@ -93,25 +94,27 @@ static BufferView NativeStorageBuffer(RenderContext&
const auto& graphics = context.GetGraphics();
const auto alignment = graphics.StorageMinAlignment();
if (alignment == 0 ||
size > graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange ||
BufferCache::CACHING_PAGE_SIZE % alignment != 0) {
size > graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange) {
EXIT("storage buffer range or device alignment is unsupported\n");
}
auto binding = context.GetBufferCache().ObtainBuffer(
command_buffer, address, size, resource.written, resource.read, resource.formatted);
if (binding.offset % alignment != 0) {
EXIT("storage buffer binding is not device-aligned\n");
const auto aligned_offset = binding.offset - binding.offset % alignment;
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.buffer = binding.buffer;
result.offset = binding.offset;
result.range = static_cast<vk::DeviceSize>(size);
result.offset = aligned_offset;
result.range = static_cast<vk::DeviceSize>(size + adjustment);
return result;
}
static BufferView
NativeAddressBuffer(RenderContext& context,
CommandBuffer& command_buffer,
NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
const ShaderRecompiler::IR::AddressResource& resource,
const ShaderRecompiler::IR::ResourceSnapshot::Address& address) {
BufferView result;
@@ -122,11 +125,11 @@ NativeAddressBuffer(RenderContext& conte
if (resource.written) {
EXIT("writable address resources are unsupported\n");
}
const auto limit = resource.kind == ShaderRecompiler::IR::ResourceKind::Flat
? ShaderRecompiler::IR::FlatAddressWindowSize
: static_cast<uint64_t>(context.GetGraphics()
.GetPhysicalDeviceProperties()
.limits.maxStorageBufferRange);
const auto limit =
resource.kind == ShaderRecompiler::IR::ResourceKind::Flat
? ShaderRecompiler::IR::FlatAddressWindowSize
: static_cast<uint64_t>(
context.GetGraphics().GetPhysicalDeviceProperties().limits.maxStorageBufferRange);
uint64_t size = 0;
const auto access = HostMemoryAccess::Mapped;
if (!HostMemoryQueryRange(address.binding_base, limit, access, size)) {
@@ -291,7 +294,7 @@ static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::Imag
descriptor.BaseArray5() == 0;
TileBlockLayout depth_block {};
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 &&
!Prospero::IsFmaskTextureFormat(descriptor.Format()) && (is_2d || is_2d_array) &&
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) ||
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
supported_depth_tile || supported_standard_tile;
const bool supported_swizzle = IsValidImageSwizzle(descriptor.DstSelXYZW()) &&
(descriptor.DstSelXYZW() == DstSel(4, 5, 6, 7) ||
!resource.read);
const bool supported_swizzle =
IsValidImageSwizzle(descriptor.DstSelXYZW()) &&
(descriptor.DstSelXYZW() == DstSel(4, 5, 6, 7) || !resource.read);
const bool supported_mip_view = descriptor.BaseLevel() == 0 || is_2d;
return (is_2d || is_2d_array || is_3d) && supported_tile && supported_mip_view &&
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.TileMode()) << 20u) |
(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);
return (descriptor.fields[1] & field1_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(),
descriptor.MaxMip(), descriptor.MinLod(), descriptor.BaseArray5(), descriptor.BCSwizzle(),
descriptor.MsaaDepth(), Prospero::RenderTargetBytesPerElement(format),
IsValidImageSwizzle(descriptor.DstSelXYZW()),
descriptor.Base40(), size, static_cast<uint32_t>(descriptor.Width5()) + 1u,
IsValidImageSwizzle(descriptor.DstSelXYZW()), descriptor.Base40(), size,
static_cast<uint32_t>(descriptor.Width5()) + 1u,
static_cast<uint32_t>(descriptor.Height5()) + 1u,
static_cast<uint32_t>(descriptor.Depth()) + 1u, descriptor.Type(), format,
descriptor.TileMode(), descriptor.DstSelXYZW(), resource.read, resource.written,
@@ -371,17 +374,15 @@ struct NullImageSpec {
static NullImageSpec NullTextureSpec(const ShaderRecompiler::IR::ImageResource& resource) {
const bool uint_image = resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint ||
resource.kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint;
return uint_image
? NullImageSpec {vk::Format::eR32Uint,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt)}
: NullImageSpec {vk::Format::eR32Sfloat,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float)};
return uint_image ? NullImageSpec {vk::Format::eR32Uint,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt)}
: NullImageSpec {vk::Format::eR32Sfloat,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float)};
}
static TextureCache::ImageDesc
NullTextureDesc(const ShaderRecompiler::IR::ImageResource& resource,
TextureCache::BindingType binding) {
const auto spec = NullTextureSpec(resource);
static TextureCache::ImageDesc NullTextureDesc(const ShaderRecompiler::IR::ImageResource& resource,
TextureCache::BindingType binding) {
const auto spec = NullTextureSpec(resource);
TextureCache::ImageDesc desc {};
desc.info.pixel_format = spec.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.type = vk::ImageViewType::e2D;
desc.view_info.aspect = vk::ImageAspectFlagBits::eColor;
desc.view_info.usage =
binding == TextureCache::BindingType::Storage ? vk::ImageUsageFlagBits::eStorage
: vk::ImageUsageFlagBits::eSampled;
desc.view_info.usage = binding == TextureCache::BindingType::Storage
? vk::ImageUsageFlagBits::eStorage
: vk::ImageUsageFlagBits::eSampled;
desc.type = binding;
return desc;
}
@@ -446,8 +447,7 @@ static void PopulateTextureMipLayout(ImageInfo& info) {
static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderTextureResource& descriptor, vk::Format format,
bool storage, uint32_t view_levels,
uint32_t image_layers) {
bool storage, uint32_t view_levels, uint32_t image_layers) {
ImageViewInfo view {};
view.format = format;
view.aspect = vk::ImageAspectFlagBits::eColor;
@@ -480,8 +480,8 @@ static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource&
}
DescriptorCache::TextureBinding
RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderRecompiler::IR::DescriptorValue& value) {
RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderRecompiler::IR::DescriptorValue& value) {
ShaderTextureResource descriptor;
CopyNativeDescriptor(value, descriptor.fields);
const bool storage = resource.written;
@@ -491,9 +491,9 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
auto& texture_cache = m_context.GetTextureCache();
if (descriptor.IsNull()) {
auto desc = NullTextureDesc(resource, storage ? TextureCache::BindingType::Storage
: TextureCache::BindingType::Texture);
const auto id = texture_cache.FindImage(desc);
auto desc = NullTextureDesc(resource, storage ? TextureCache::BindingType::Storage
: TextureCache::BindingType::Texture);
const auto id = texture_cache.FindImage(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 type = TextureType(descriptor);
const bool multisampled =
type == Prospero::ImageType::kColor2DMsaa ||
type == Prospero::ImageType::kColor2DMsaaArray;
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
const auto tile = descriptor.TileMode();
const bool msaa_tile =
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
type == Prospero::ImageType::kColor2DMsaa || type == Prospero::ImageType::kColor2DMsaaArray;
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
const auto tile = descriptor.TileMode();
const bool msaa_tile = tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
const bool msaa_array = type == Prospero::ImageType::kColor2DMsaaArray;
if ((!multisampled && (base_level > last_level || last_level >= levels)) ||
(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,
levels);
}
const auto samples = multisampled ? 1u << last_level : 1u;
const auto samples = multisampled ? 1u << last_level : 1u;
const auto view_levels =
multisampled ? 1u : static_cast<uint32_t>(last_level - base_level) + 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);
}
const bool volume = type == Prospero::ImageType::kColor3D;
const bool layered = type == Prospero::ImageType::kColor1DArray ||
type == Prospero::ImageType::kColor2DArray ||
type == Prospero::ImageType::kColor2DMsaaArray;
const auto image_layers = layered ? depth : 1u;
uint32_t pitch = 0;
const bool volume = type == Prospero::ImageType::kColor3D;
const bool layered = type == Prospero::ImageType::kColor1DArray ||
type == Prospero::ImageType::kColor2DArray ||
type == Prospero::ImageType::kColor2DMsaaArray;
const auto image_layers = layered ? depth : 1u;
uint32_t pitch = 0;
TileSizeAlign size {};
if (multisampled) {
const auto bytes = Prospero::NumBytesPerElement(format);
pitch = TileGetRenderTargetPitch(width, bytes, last_level);
if (pitch == 0 ||
!TileGetRenderTargetSize(width, height, pitch, bytes, size, last_level) ||
if (pitch == 0 || !TileGetRenderTargetSize(width, height, pitch, bytes, size, last_level) ||
size.size > UINT32_MAX / image_layers) {
EXIT("unsupported multisample texture layout\n");
}
size.size *= image_layers;
} else {
pitch = TileGetTexturePitch(format, width, levels, tile);
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, pitch,
levels, tile, volume, size);
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, pitch, levels,
tile, volume, size);
}
EXIT_NOT_IMPLEMENTED(size.size == 0 || size.align == 0 ||
(address & (static_cast<uint64_t>(size.align) - 1u)) != 0);
@@ -564,8 +561,8 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
resource.written);
}
const auto pixel_format = TextureGetFormat(format);
const auto block_bytes = Prospero::BlockCompressedBytesPerBlock(format);
const auto pixel_format = TextureGetFormat(format);
const auto block_bytes = Prospero::BlockCompressedBytesPerBlock(format);
TextureCache::ImageDesc desc {};
desc.info.data = {address, size.size};
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.info.resources.layers);
desc.type = storage ? TextureCache::BindingType::Storage
: TextureCache::BindingType::Texture;
desc.type = storage ? TextureCache::BindingType::Storage : TextureCache::BindingType::Texture;
auto id = texture_cache.FindImage(desc);
auto* image = &texture_cache.GetImage(id);
auto id = texture_cache.FindImage(desc);
auto* image = &texture_cache.GetImage(id);
const bool stencil_association = static_cast<bool>(image->depth_id);
if (stencil_association) {
id = image->depth_id;
@@ -610,7 +606,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& resour
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::DescriptorValue& value) {
ShaderSamplerResource descriptor;
@@ -631,8 +627,7 @@ static BufferView NativeUpload(RenderContext& context, CommandBuffer& command_bu
std::span<const uint32_t> data) {
EXIT_IF(data.empty());
EXIT_IF(command_buffer.IsInvalid() || command_buffer.IsExecute());
auto binding =
context.GetBufferCache().UploadTransient(data.data(), data.size_bytes(), 256);
auto binding = context.GetBufferCache().UploadTransient(data.data(), data.size_bytes(), 256);
return {.owner = std::move(binding.owner),
.buffer = binding.buffer,
.offset = binding.offset,
@@ -660,8 +655,8 @@ void RenderExecutor::BindImage(ImageId id, bool storage) {
}
void RenderExecutor::BindRenderTarget(ImageId id) {
auto& image = m_context.GetTextureCache().GetImage(id);
image.binding.is_target = true;
auto& image = m_context.GetTextureCache().GetImage(id);
image.binding.is_target = true;
TrackImageBinding(id);
}
@@ -672,9 +667,10 @@ void RenderExecutor::ResetBindings() {
m_bound_images.clear();
}
DescriptorCache::PreparedBindings
RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime& runtime,
vk::ShaderStageFlags shader_stage, DescriptorCache::Stage stage) {
DescriptorCache::PreparedBindings RenderExecutor::PrepareBindings(CommandBuffer& buffer,
const ShaderStageRuntime& runtime,
vk::ShaderStageFlags shader_stage,
DescriptorCache::Stage stage) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(!runtime);
const auto& program = *runtime.program;
@@ -691,12 +687,6 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
prepared.stage = stage;
auto& descriptors = prepared.resources;
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());
for (uint32_t i = 0; i < program.info.images.size(); 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());
for (uint32_t i = 0; i < program.info.samplers.size(); i++) {
descriptors.samplers.push_back(
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]));
descriptors.samplers.push_back(NativeSampler(m_context, program, i, snapshot.samplers[i]));
}
if (ShaderRecompiler::IR::FindBinding(
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.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) {
prepared.user_data.push_back(snapshot.user_data[reg - program.user_data_base]);
}
prepared.user_data.resize(program.bindings.ShaderDataDwords());
if (ShaderRecompiler::IR::FindBinding(
program.bindings, ShaderRecompiler::IR::DescriptorBindingKind::Gds) != nullptr) {
descriptors.gds.buffer = m_context.GetBufferCache().GetGdsBuffer().Handle();
@@ -730,21 +715,28 @@ RenderExecutor::PrepareBindings(CommandBuffer& buffer, const ShaderStageRuntime&
return prepared;
}
void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
DescriptorCache::PreparedBindings& prepared) {
void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
DescriptorCache::PreparedBindings& prepared) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
const auto& program = *prepared.program;
const auto& snapshot = *prepared.snapshot;
auto& resources = prepared.resources;
const auto& layout = program.bindings;
resources.buffers.clear();
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++) {
ShaderBufferResource descriptor;
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
resources.buffers.push_back(
NativeStorageBuffer(m_context, buffer, descriptor, program.info.buffers[i]));
uint32_t buffer_offset = 0;
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.reserve(program.info.addresses.size());
@@ -754,8 +746,8 @@ void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
}
}
void RenderExecutor::RebindImages(CommandBuffer& buffer,
DescriptorCache::PreparedBindings& prepared) {
void RenderExecutor::RebindImages(CommandBuffer& buffer,
DescriptorCache::PreparedBindings& prepared) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(prepared.program == nullptr || prepared.snapshot == nullptr);
const auto& program = *prepared.program;
@@ -765,8 +757,7 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
auto& texture_cache = m_context.GetTextureCache();
for (uint32_t i = 0; i < program.info.images.size(); i++) {
const auto old_image = texture_cache.ResolveOwner(images[i].image_id);
if (old_image == nullptr ||
(!old_image->registered && !old_image->info.data.Empty()) ||
if (old_image == nullptr || (!old_image->registered && !old_image->info.data.Empty()) ||
old_image->binding.needs_rebind) {
if (old_image != nullptr) {
old_image->binding = {};
@@ -775,10 +766,10 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
BindImage(images[i].image_id,
images[i].desc.type == TextureCache::BindingType::Storage);
}
auto& binding = images[i];
binding.image_view = texture_cache.FindTexture(binding.image_id, binding.desc);
auto& image = texture_cache.GetImage(binding.image_id);
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
auto& binding = images[i];
binding.image_view = texture_cache.FindTexture(binding.image_id, binding.desc);
auto& image = texture_cache.GetImage(binding.image_id);
const bool storage = binding.desc.type == TextureCache::BindingType::Storage;
image.usage.storage |= storage;
image.usage.texture |= !storage;
}
@@ -786,7 +777,7 @@ void RenderExecutor::RebindImages(CommandBuffer& buffer,
RenderExecutor::GraphicsBindings
RenderExecutor::PrepareGraphicsBindings(CommandBuffer& buffer, const ShaderStageRuntime& vertex,
const ShaderStageRuntime& pixel, bool pixel_active) {
const ShaderStageRuntime& pixel, bool pixel_active) {
GraphicsBindings bindings {
.vertex = PrepareBindings(buffer, vertex, vk::ShaderStageFlagBits::eVertex,
DescriptorCache::Stage::Vertex),
@@ -822,10 +813,10 @@ static void RetainBindings(CommandBuffer& buffer,
}
}
void RenderExecutor::CommitBindings(CommandBuffer& buffer,
vk::PipelineBindPoint pipeline_bind_point,
vk::PipelineLayout layout,
DescriptorCache::PreparedBindings& prepared) {
void RenderExecutor::CommitBindings(CommandBuffer& buffer,
vk::PipelineBindPoint pipeline_bind_point,
vk::PipelineLayout layout,
DescriptorCache::PreparedBindings& prepared) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(prepared.program == nullptr || prepared.stage == DescriptorCache::Stage::Unknown ||
prepared.committed);
@@ -852,7 +843,7 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
}
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];
const auto& view = binding.desc.view_info;
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;
if (image.info.data.Empty()) {
image.Transit(vk::ImageLayout::eGeneral,
storage ? vk::AccessFlagBits2::eShaderRead |
vk::AccessFlagBits2::eShaderWrite
: vk::AccessFlagBits2::eShaderRead,
storage
? vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite
: vk::AccessFlagBits2::eShaderRead,
range, vk_buffer);
} else if ((image.binding.force_general || image.binding.is_target) &&
!image.info.IsDepth()) {
@@ -877,7 +868,7 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
range, vk_buffer);
} else {
image.Transit(image.info.IsDepth() ? vk::ImageLayout::eDepthStencilReadOnlyOptimal
: vk::ImageLayout::eShaderReadOnlyOptimal,
: vk::ImageLayout::eShaderReadOnlyOptimal,
vk::AccessFlagBits2::eShaderRead, range, vk_buffer);
}
binding.layout = image.backing.state.layout;