renderer_vulkan: Fix allocation caching bug
This commit is contained in:
@ -117,20 +117,26 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
const vk::Format vk_format = is_suitable ? traits.native : traits.fallback;
|
const vk::Format vk_format = is_suitable ? traits.native : traits.fallback;
|
||||||
const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect);
|
const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect);
|
||||||
|
|
||||||
return Allocate(width, height, type, vk_format, vk_usage,
|
return Allocate(width, height, format, type, vk_format, vk_usage);
|
||||||
format == VideoCore::PixelFormat::RGBA8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::TextureType type,
|
ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format,
|
||||||
vk::Format format, vk::ImageUsageFlags usage,
|
VideoCore::TextureType type, vk::Format format,
|
||||||
bool create_storage_view) {
|
vk::ImageUsageFlags usage) {
|
||||||
ImageAlloc alloc{};
|
ImageAlloc alloc{};
|
||||||
alloc.format = format;
|
alloc.format = format;
|
||||||
alloc.levels = std::bit_width(std::max(width, height));
|
alloc.levels = std::bit_width(std::max(width, height));
|
||||||
alloc.layers = type == VideoCore::TextureType::CubeMap ? 6 : 1;
|
alloc.layers = type == VideoCore::TextureType::CubeMap ? 6 : 1;
|
||||||
alloc.aspect = GetImageAspect(format);
|
alloc.aspect = GetImageAspect(format);
|
||||||
|
|
||||||
const HostTextureTag key = {.format = format, .type = type, .width = width, .height = height};
|
// The internal format does not provide enough guarantee of texture uniqueness
|
||||||
|
// especially when many pixel formats fallback to RGBA8
|
||||||
|
ASSERT(pixel_format != VideoCore::PixelFormat::Invalid);
|
||||||
|
const HostTextureTag key = {.format = format,
|
||||||
|
.pixel_format = pixel_format,
|
||||||
|
.type = type,
|
||||||
|
.width = width,
|
||||||
|
.height = height};
|
||||||
|
|
||||||
// Attempt to recycle an unused allocation
|
// Attempt to recycle an unused allocation
|
||||||
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
|
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
|
||||||
@ -139,6 +145,8 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::TextureTyp
|
|||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool create_storage_view = pixel_format == VideoCore::PixelFormat::RGBA8;
|
||||||
|
|
||||||
vk::ImageCreateFlags flags;
|
vk::ImageCreateFlags flags;
|
||||||
if (type == VideoCore::TextureType::CubeMap) {
|
if (type == VideoCore::TextureType::CubeMap) {
|
||||||
flags |= vk::ImageCreateFlagBits::eCubeCompatible;
|
flags |= vk::ImageCreateFlagBits::eCubeCompatible;
|
||||||
@ -598,13 +606,15 @@ Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format,
|
|||||||
: VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
: VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()},
|
||||||
scheduler{runtime.GetScheduler()} {
|
scheduler{runtime.GetScheduler()} {
|
||||||
if (format != vk::Format::eUndefined) {
|
if (format != vk::Format::eUndefined) {
|
||||||
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), texture_type, format, usage);
|
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), pixel_format, texture_type,
|
||||||
|
format, usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface::~Surface() {
|
Surface::~Surface() {
|
||||||
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
||||||
const HostTextureTag tag = {.format = alloc.format,
|
const HostTextureTag tag = {.format = alloc.format,
|
||||||
|
.pixel_format = pixel_format,
|
||||||
.type = texture_type,
|
.type = texture_type,
|
||||||
.width = GetScaledWidth(),
|
.width = GetScaledWidth(),
|
||||||
.height = GetScaledHeight()};
|
.height = GetScaledHeight()};
|
||||||
@ -800,7 +810,9 @@ void Surface::DepthStencilDownload(const VideoCore::BufferTextureCopy& download,
|
|||||||
VideoCore::Rect2D{0, scaled_rect.GetHeight(), scaled_rect.GetWidth(), 0};
|
VideoCore::Rect2D{0, scaled_rect.GetHeight(), scaled_rect.GetWidth(), 0};
|
||||||
|
|
||||||
// For depth downloads create an R32UI surface and use a compute shader for convert.
|
// For depth downloads create an R32UI surface and use a compute shader for convert.
|
||||||
// Then we blit and download that surface
|
// Then we blit and download that surface.
|
||||||
|
// NOTE: We don't need to set pixel format here since R32Uint automatically gives us
|
||||||
|
// a storage view. Also the D24S8 creates a unique cache key for it
|
||||||
SurfaceParams r32_params = *this;
|
SurfaceParams r32_params = *this;
|
||||||
r32_params.width = scaled_rect.GetWidth();
|
r32_params.width = scaled_rect.GetWidth();
|
||||||
r32_params.stride = scaled_rect.GetWidth();
|
r32_params.stride = scaled_rect.GetWidth();
|
||||||
|
@ -51,6 +51,7 @@ struct ImageAlloc {
|
|||||||
|
|
||||||
struct HostTextureTag {
|
struct HostTextureTag {
|
||||||
vk::Format format = vk::Format::eUndefined;
|
vk::Format format = vk::Format::eUndefined;
|
||||||
|
VideoCore::PixelFormat pixel_format = VideoCore::PixelFormat::Invalid;
|
||||||
VideoCore::TextureType type = VideoCore::TextureType::Texture2D;
|
VideoCore::TextureType type = VideoCore::TextureType::Texture2D;
|
||||||
u32 width = 1;
|
u32 width = 1;
|
||||||
u32 height = 1;
|
u32 height = 1;
|
||||||
@ -99,9 +100,9 @@ public:
|
|||||||
VideoCore::TextureType type);
|
VideoCore::TextureType type);
|
||||||
|
|
||||||
/// Allocates a vulkan image
|
/// Allocates a vulkan image
|
||||||
[[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::TextureType type,
|
[[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format,
|
||||||
vk::Format format, vk::ImageUsageFlags usage,
|
VideoCore::TextureType type, vk::Format format,
|
||||||
bool create_storage_view = false);
|
vk::ImageUsageFlags usage);
|
||||||
|
|
||||||
/// Causes a GPU command flush
|
/// Causes a GPU command flush
|
||||||
void Finish();
|
void Finish();
|
||||||
@ -208,7 +209,13 @@ public:
|
|||||||
|
|
||||||
/// Returns the R32 image view used for atomic load/store
|
/// Returns the R32 image view used for atomic load/store
|
||||||
vk::ImageView GetStorageView() const {
|
vk::ImageView GetStorageView() const {
|
||||||
ASSERT(alloc.storage_view);
|
if (!alloc.storage_view) {
|
||||||
|
LOG_CRITICAL(Render_Vulkan,
|
||||||
|
"Surface with pixel format {} and internal format {} "
|
||||||
|
"does not provide requested storage view!",
|
||||||
|
VideoCore::PixelFormatAsString(pixel_format), vk::to_string(alloc.format));
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
return alloc.storage_view;
|
return alloc.storage_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user