diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 6bc2ba61d..e223bbaf1 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -116,11 +116,13 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept { const auto& attrib = group.attrib; is_tiled = attrib.tiling_mode == TilingMode::Tile; + tiling_mode = + is_tiled ? AmdGpu::TilingMode::Display_MacroTiled : AmdGpu::TilingMode::Display_Linear; pixel_format = ConvertPixelFormat(attrib.pixel_format); type = vk::ImageType::e2D; size.width = attrib.width; size.height = attrib.height; - pitch = attrib.tiling_mode == TilingMode::Linear ? size.width : (size.width + 127) >> 7; + pitch = attrib.tiling_mode == TilingMode::Linear ? size.width : (size.width + 127) & (~127); const bool is_32bpp = attrib.pixel_format != VideoOutFormat::A16R16G16B16Float; ASSERT(is_32bpp); if (!is_tiled) { @@ -128,11 +130,11 @@ ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noe return; } if (Config::isNeoMode()) { - guest_size_bytes = pitch * 128 * ((size.height + 127) & (~127)) * 4; + guest_size_bytes = pitch * ((size.height + 127) & (~127)) * 4; } else { - guest_size_bytes = pitch * 128 * ((size.height + 63) & (~63)) * 4; + guest_size_bytes = pitch * ((size.height + 63) & (~63)) * 4; } - is_vo_surface = true; + usage.vo_buffer = true; } ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, @@ -140,12 +142,14 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, is_tiled = buffer.IsTiled(); tiling_mode = buffer.GetTilingMode(); pixel_format = LiverpoolToVK::SurfaceFormat(buffer.info.format, buffer.NumFormat()); + num_samples = 1 << buffer.attrib.num_fragments_log2; type = vk::ImageType::e2D; size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); size.depth = 1; pitch = size.width; guest_size_bytes = buffer.GetSizeAligned(); + usage.render_target = true; } ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, @@ -153,11 +157,13 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, is_tiled = false; pixel_format = LiverpoolToVK::DepthFormat(buffer.z_info.format, buffer.stencil_info.format); type = vk::ImageType::e2D; + num_samples = 1 << buffer.z_info.num_samples; // spec doesn't say it is a log2 size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); size.depth = 1; pitch = size.width; guest_size_bytes = buffer.GetSizeAligned(); + usage.depth_target = true; } ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { @@ -222,7 +228,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, } } - info.usage = ImageUsageFlags(info); + usage = ImageUsageFlags(info); if (info.pixel_format == vk::Format::eD32Sfloat) { aspect_mask = vk::ImageAspectFlagBits::eDepth; @@ -243,7 +249,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, .mipLevels = static_cast(info.resources.levels), .arrayLayers = static_cast(info.resources.layers), .tiling = vk::ImageTiling::eOptimal, - .usage = info.usage, + .usage = usage, .initialLayout = vk::ImageLayout::eUndefined, }; diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index d7377e79a..2964379f1 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -42,18 +42,28 @@ struct ImageInfo { const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; explicit ImageInfo(const AmdGpu::Image& image) noexcept; + bool IsTiled() const { + return tiling_mode != AmdGpu::TilingMode::Display_Linear; + } bool IsBlockCoded() const; bool IsPacked() const; bool IsDepthStencil() const; + struct { + u32 texture : 1; + u32 storage : 1; + u32 render_target : 1; + u32 depth_target : 1; + u32 vo_buffer : 1; + } usage; // Usage data tracked during image lifetime + bool is_tiled = false; bool is_storage = false; - bool is_vo_surface = false; vk::Format pixel_format = vk::Format::eUndefined; vk::ImageType type = vk::ImageType::e1D; - vk::ImageUsageFlags usage; SubresourceExtent resources; Extent3D size{1, 1, 1}; + u32 num_samples = 1; u32 pitch = 0; u32 guest_size_bytes = 0; AmdGpu::TilingMode tiling_mode{AmdGpu::TilingMode::Display_Linear}; @@ -132,6 +142,7 @@ struct Image { std::optional view_for_detiler; // Resource state tracking + vk::ImageUsageFlags usage; vk::Flags pl_stage = vk::PipelineStageFlagBits::eAllCommands; vk::Flags access_mask = vk::AccessFlagBits::eNone; vk::ImageLayout layout = vk::ImageLayout::eUndefined; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index f58bdcf2b..441124230 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -151,7 +151,7 @@ ImageView& TextureCache::RegisterImageView(Image& image, const ImageViewInfo& vi // temporary remove its storage bit. std::optional usage_override; if (!image.info.is_storage) { - usage_override = image.info.usage & ~vk::ImageUsageFlagBits::eStorage; + usage_override = image.usage & ~vk::ImageUsageFlagBits::eStorage; } const ImageViewId view_id = slot_image_views.insert(instance, view_info, image, usage_override); @@ -183,7 +183,7 @@ ImageView& TextureCache::RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buff vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead); - ImageViewInfo view_info{buffer, image.info.is_vo_surface}; + ImageViewInfo view_info{buffer, !!image.info.usage.vo_buffer}; return RegisterImageView(image, view_info); }