|
|
|
@@ -292,7 +292,7 @@ namespace vk
|
|
|
|
|
verify(HERE), miss;
|
|
|
|
|
|
|
|
|
|
// Replace the wait event with a new one to avoid premature signaling!
|
|
|
|
|
vk::get_resource_manager->dispose(dma_fence);
|
|
|
|
|
vk::get_resource_manager()->dispose(dma_fence);
|
|
|
|
|
|
|
|
|
|
VkEventCreateInfo createInfo = {};
|
|
|
|
|
createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
|
|
|
@@ -369,35 +369,22 @@ namespace vk
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct discarded_storage
|
|
|
|
|
struct temporary_storage
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<vk::viewable_image> combined_image;
|
|
|
|
|
std::unique_ptr<vk::image_view> view;
|
|
|
|
|
std::unique_ptr<vk::image> img;
|
|
|
|
|
|
|
|
|
|
//Memory held by this temp storage object
|
|
|
|
|
// Memory held by this temp storage object
|
|
|
|
|
u32 block_size = 0;
|
|
|
|
|
|
|
|
|
|
//Frame id tag
|
|
|
|
|
// Frame id tag
|
|
|
|
|
const u64 frame_tag = vk::get_current_frame_id();
|
|
|
|
|
|
|
|
|
|
discarded_storage(std::unique_ptr<vk::image_view>& _view)
|
|
|
|
|
temporary_storage(std::unique_ptr<vk::viewable_image>& _img)
|
|
|
|
|
{
|
|
|
|
|
view = std::move(_view);
|
|
|
|
|
combined_image = std::move(_img);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
discarded_storage(std::unique_ptr<vk::image>& _img)
|
|
|
|
|
{
|
|
|
|
|
img = std::move(_img);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
discarded_storage(std::unique_ptr<vk::image>& _img, std::unique_ptr<vk::image_view>& _view)
|
|
|
|
|
{
|
|
|
|
|
img = std::move(_img);
|
|
|
|
|
view = std::move(_view);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
discarded_storage(vk::cached_texture_section& tex)
|
|
|
|
|
temporary_storage(vk::cached_texture_section& tex)
|
|
|
|
|
{
|
|
|
|
|
combined_image = std::move(tex.get_texture());
|
|
|
|
|
block_size = tex.get_section_size();
|
|
|
|
@@ -407,6 +394,21 @@ namespace vk
|
|
|
|
|
{
|
|
|
|
|
return ref_frame > 0 && frame_tag <= ref_frame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool matches(VkFormat format, u16 w, u16 h, u16 d, VkFlags flags) const
|
|
|
|
|
{
|
|
|
|
|
if (combined_image &&
|
|
|
|
|
combined_image->info.flags == flags &&
|
|
|
|
|
combined_image->format() == format &&
|
|
|
|
|
combined_image->width() == w &&
|
|
|
|
|
combined_image->height() == h &&
|
|
|
|
|
combined_image->depth() == d)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class texture_cache : public rsx::texture_cache<vk::texture_cache, vk::texture_cache_traits>
|
|
|
|
@@ -420,8 +422,8 @@ namespace vk
|
|
|
|
|
{
|
|
|
|
|
if (tex.is_managed())
|
|
|
|
|
{
|
|
|
|
|
m_discarded_memory_size += tex.get_section_size();
|
|
|
|
|
m_discardable_storage.emplace_back(tex);
|
|
|
|
|
m_temporary_memory_size += tex.get_section_size();
|
|
|
|
|
m_temporary_storage.emplace_back(tex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -435,15 +437,15 @@ namespace vk
|
|
|
|
|
vk::data_heap* m_texture_upload_heap;
|
|
|
|
|
|
|
|
|
|
//Stuff that has been dereferenced goes into these
|
|
|
|
|
std::list<discarded_storage> m_discardable_storage;
|
|
|
|
|
std::atomic<u32> m_discarded_memory_size = { 0 };
|
|
|
|
|
std::list<temporary_storage> m_temporary_storage;
|
|
|
|
|
std::atomic<u32> m_temporary_memory_size = { 0 };
|
|
|
|
|
|
|
|
|
|
void clear()
|
|
|
|
|
{
|
|
|
|
|
baseclass::clear();
|
|
|
|
|
|
|
|
|
|
m_discardable_storage.clear();
|
|
|
|
|
m_discarded_memory_size = 0;
|
|
|
|
|
m_temporary_storage.clear();
|
|
|
|
|
m_temporary_memory_size = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const texture_channel_remap_t& remap_vector) const
|
|
|
|
@@ -678,22 +680,64 @@ namespace vk
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<vk::viewable_image> find_temporary_image(VkFormat format, u16 w, u16 h, u16 d)
|
|
|
|
|
{
|
|
|
|
|
const auto current_frame = vk::get_current_frame_id();
|
|
|
|
|
for (auto &e : m_temporary_storage)
|
|
|
|
|
{
|
|
|
|
|
if (e.frame_tag != current_frame && e.matches(format, w, h, d, 0))
|
|
|
|
|
{
|
|
|
|
|
m_temporary_memory_size -= e.block_size;
|
|
|
|
|
e.block_size = 0;
|
|
|
|
|
return std::move(e.combined_image);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<vk::viewable_image> find_temporary_cubemap(VkFormat format, u16 size)
|
|
|
|
|
{
|
|
|
|
|
const auto current_frame = vk::get_current_frame_id();
|
|
|
|
|
for (auto &e : m_temporary_storage)
|
|
|
|
|
{
|
|
|
|
|
if (e.frame_tag != current_frame && e.matches(format, size, size, 1, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
|
|
|
|
|
{
|
|
|
|
|
m_temporary_memory_size -= e.block_size;
|
|
|
|
|
e.block_size = 0;
|
|
|
|
|
return std::move(e.combined_image);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type,
|
|
|
|
|
u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector, bool copy)
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<vk::image> image;
|
|
|
|
|
std::unique_ptr<vk::image_view> view;
|
|
|
|
|
std::unique_ptr<vk::viewable_image> image;
|
|
|
|
|
|
|
|
|
|
VkImageCreateFlags image_flags = (view_type == VK_IMAGE_VIEW_TYPE_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
|
|
|
|
|
VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format);
|
|
|
|
|
VkImageAspectFlags aspect = vk::get_aspect_flags(dst_format);
|
|
|
|
|
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
image_type,
|
|
|
|
|
dst_format,
|
|
|
|
|
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags);
|
|
|
|
|
if (LIKELY(!image_flags))
|
|
|
|
|
{
|
|
|
|
|
image = find_temporary_image(dst_format, w, h, 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
image = find_temporary_cubemap(dst_format, w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!image)
|
|
|
|
|
{
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
image_type,
|
|
|
|
|
dst_format,
|
|
|
|
|
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//This method is almost exclusively used to work on framebuffer resources
|
|
|
|
|
//Keep the original swizzle layout unless there is data format conversion
|
|
|
|
@@ -711,12 +755,8 @@ namespace vk
|
|
|
|
|
view_swizzle = source->native_component_map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (memcmp(remap_vector.first.data(), rsx::default_remap_vector.first.data(), 4) ||
|
|
|
|
|
memcmp(remap_vector.second.data(), rsx::default_remap_vector.second.data(), 4))
|
|
|
|
|
view_swizzle = vk::apply_swizzle_remap({view_swizzle.a, view_swizzle.r, view_swizzle.g, view_swizzle.b}, remap_vector);
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
|
|
|
|
view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), image.get(), view_swizzle, view_range);
|
|
|
|
|
image->set_native_component_layout(view_swizzle);
|
|
|
|
|
auto view = image->get_view(get_remap_encoding(remap_vector), remap_vector);
|
|
|
|
|
|
|
|
|
|
if (copy)
|
|
|
|
|
{
|
|
|
|
@@ -734,11 +774,11 @@ namespace vk
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u32 resource_memory = w * h * 4; //Rough approximate
|
|
|
|
|
m_discardable_storage.emplace_back(image, view);
|
|
|
|
|
m_discardable_storage.back().block_size = resource_memory;
|
|
|
|
|
m_discarded_memory_size += resource_memory;
|
|
|
|
|
m_temporary_storage.emplace_back(image);
|
|
|
|
|
m_temporary_storage.back().block_size = resource_memory;
|
|
|
|
|
m_temporary_memory_size += resource_memory;
|
|
|
|
|
|
|
|
|
|
return m_discardable_storage.back().view.get();
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format,
|
|
|
|
@@ -757,20 +797,20 @@ namespace vk
|
|
|
|
|
vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size,
|
|
|
|
|
const std::vector<copy_region_descriptor>& sections_to_copy, const texture_channel_remap_t& /*remap_vector*/) override
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<vk::image> image;
|
|
|
|
|
std::unique_ptr<vk::image_view> view;
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<vk::viewable_image> image;
|
|
|
|
|
VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format);
|
|
|
|
|
VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format);
|
|
|
|
|
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
|
dst_format,
|
|
|
|
|
size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
|
|
|
|
|
if (image = find_temporary_cubemap(dst_format, size); !image)
|
|
|
|
|
{
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
|
dst_format,
|
|
|
|
|
size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 6 };
|
|
|
|
|
view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range);
|
|
|
|
|
auto view = image->get_view(0xAAE4, rsx::default_remap_vector);
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 6 };
|
|
|
|
|
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range);
|
|
|
|
@@ -791,30 +831,30 @@ namespace vk
|
|
|
|
|
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range);
|
|
|
|
|
|
|
|
|
|
const u32 resource_memory = size * size * 6 * 4; //Rough approximate
|
|
|
|
|
m_discardable_storage.emplace_back(image, view);
|
|
|
|
|
m_discardable_storage.back().block_size = resource_memory;
|
|
|
|
|
m_discarded_memory_size += resource_memory;
|
|
|
|
|
m_temporary_storage.emplace_back(image);
|
|
|
|
|
m_temporary_storage.back().block_size = resource_memory;
|
|
|
|
|
m_temporary_memory_size += resource_memory;
|
|
|
|
|
|
|
|
|
|
return m_discardable_storage.back().view.get();
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk::image_view* generate_3d_from_2d_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, u16 depth,
|
|
|
|
|
const std::vector<copy_region_descriptor>& sections_to_copy, const texture_channel_remap_t& /*remap_vector*/) override
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<vk::image> image;
|
|
|
|
|
std::unique_ptr<vk::image_view> view;
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<vk::viewable_image> image;
|
|
|
|
|
VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format);
|
|
|
|
|
VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format);
|
|
|
|
|
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
VK_IMAGE_TYPE_3D,
|
|
|
|
|
dst_format,
|
|
|
|
|
width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0);
|
|
|
|
|
if (image = find_temporary_image(dst_format, width, height, depth); !image)
|
|
|
|
|
{
|
|
|
|
|
image = std::make_unique<vk::viewable_image>(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
|
VK_IMAGE_TYPE_3D,
|
|
|
|
|
dst_format,
|
|
|
|
|
width, height, depth, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange view_range = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
|
|
|
|
view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), image.get(), image->native_component_map, view_range);
|
|
|
|
|
auto view = image->get_view(0xAAE4, rsx::default_remap_vector);
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 1 };
|
|
|
|
|
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range);
|
|
|
|
@@ -835,11 +875,11 @@ namespace vk
|
|
|
|
|
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range);
|
|
|
|
|
|
|
|
|
|
const u32 resource_memory = width * height * depth * 4; //Rough approximate
|
|
|
|
|
m_discardable_storage.emplace_back(image, view);
|
|
|
|
|
m_discardable_storage.back().block_size = resource_memory;
|
|
|
|
|
m_discarded_memory_size += resource_memory;
|
|
|
|
|
m_temporary_storage.emplace_back(image);
|
|
|
|
|
m_temporary_storage.back().block_size = resource_memory;
|
|
|
|
|
m_temporary_memory_size += resource_memory;
|
|
|
|
|
|
|
|
|
|
return m_discardable_storage.back().view.get();
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height,
|
|
|
|
@@ -1189,17 +1229,17 @@ namespace vk
|
|
|
|
|
void on_frame_end() override
|
|
|
|
|
{
|
|
|
|
|
if (m_storage.m_unreleased_texture_objects >= m_max_zombie_objects ||
|
|
|
|
|
m_discarded_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources
|
|
|
|
|
m_temporary_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources
|
|
|
|
|
{
|
|
|
|
|
purge_unreleased_sections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 last_complete_frame = vk::get_last_completed_frame_id();
|
|
|
|
|
m_discardable_storage.remove_if([&](const discarded_storage& o)
|
|
|
|
|
m_temporary_storage.remove_if([&](const temporary_storage& o)
|
|
|
|
|
{
|
|
|
|
|
if (o.test(last_complete_frame))
|
|
|
|
|
if (!o.block_size || o.test(last_complete_frame))
|
|
|
|
|
{
|
|
|
|
|
m_discarded_memory_size -= o.block_size;
|
|
|
|
|
m_temporary_memory_size -= o.block_size;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
@@ -1219,7 +1259,7 @@ namespace vk
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Uploads a linear memory range as a BGRA8 texture
|
|
|
|
|
auto image = std::make_unique<vk::image>(*m_device, m_memory_types.host_visible_coherent,
|
|
|
|
|
auto image = std::make_unique<vk::viewable_image>(*m_device, m_memory_types.host_visible_coherent,
|
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM,
|
|
|
|
@@ -1257,9 +1297,9 @@ namespace vk
|
|
|
|
|
|
|
|
|
|
auto result = image.get();
|
|
|
|
|
const u32 resource_memory = width * height * 4; //Rough approximate
|
|
|
|
|
m_discardable_storage.emplace_back(image);
|
|
|
|
|
m_discardable_storage.back().block_size = resource_memory;
|
|
|
|
|
m_discarded_memory_size += resource_memory;
|
|
|
|
|
m_temporary_storage.emplace_back(image);
|
|
|
|
|
m_temporary_storage.back().block_size = resource_memory;
|
|
|
|
|
m_temporary_memory_size += resource_memory;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
@@ -1284,12 +1324,12 @@ namespace vk
|
|
|
|
|
|
|
|
|
|
const u32 get_unreleased_textures_count() const override
|
|
|
|
|
{
|
|
|
|
|
return baseclass::get_unreleased_textures_count() + (u32)m_discardable_storage.size();
|
|
|
|
|
return baseclass::get_unreleased_textures_count() + (u32)m_temporary_storage.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u32 get_temporary_memory_in_use()
|
|
|
|
|
{
|
|
|
|
|
return m_discarded_memory_size;
|
|
|
|
|
return m_temporary_memory_size;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|