rsx: Fixes for cubemap reconstruction

- Do not abort generation if sides are missing, replace with blank surfaces instead
- Make cubemaps scale with res scaling
This commit is contained in:
kd-11 2017-11-03 15:48:27 +03:00
parent 60c7a508a7
commit 300a36d3d6
3 changed files with 50 additions and 27 deletions

View file

@ -347,6 +347,7 @@ namespace rsx
u32 last_dirty_block = UINT32_MAX; u32 last_dirty_block = UINT32_MAX;
std::pair<u32, u32> trampled_range = std::make_pair(address, address + range); std::pair<u32, u32> trampled_range = std::make_pair(address, address + range);
const bool strict_range_check = g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer;
for (auto It = m_cache.begin(); It != m_cache.end(); It++) for (auto It = m_cache.begin(); It != m_cache.end(); It++)
{ {
@ -370,7 +371,7 @@ namespace rsx
if (tex.cache_tag == cache_tag) continue; //already processed if (tex.cache_tag == cache_tag) continue; //already processed
if (!tex.is_locked()) continue; //flushable sections can be 'clean' but unlocked. TODO: Handle this better if (!tex.is_locked()) continue; //flushable sections can be 'clean' but unlocked. TODO: Handle this better
auto overlapped = tex.overlaps_page(trampled_range, address, tex.is_flushable()); auto overlapped = tex.overlaps_page(trampled_range, address, strict_range_check);
if (std::get<0>(overlapped)) if (std::get<0>(overlapped))
{ {
auto &new_range = std::get<1>(overlapped); auto &new_range = std::get<1>(overlapped);
@ -1051,7 +1052,7 @@ namespace rsx
std::array<image_resource_type, 6> image_array; std::array<image_resource_type, 6> image_array;
image_array[0] = texptr->get_surface(); image_array[0] = texptr->get_surface();
bool can_cast = true; bool safe_cast = true;
u32 image_size = texptr->get_rsx_pitch() * texptr->get_surface_height(); u32 image_size = texptr->get_rsx_pitch() * texptr->get_surface_height();
u32 image_address = texaddr + image_size; u32 image_address = texaddr + image_size;
@ -1059,35 +1060,43 @@ namespace rsx
for (int n = 1; n < 6; ++n) for (int n = 1; n < 6; ++n)
{ {
render_target_type img = nullptr; render_target_type img = nullptr;
image_array[n] = 0;
if (!!(img = m_rtts.get_texture_from_render_target_if_applicable(image_address)) || if (!!(img = m_rtts.get_texture_from_render_target_if_applicable(image_address)) ||
!!(img = m_rtts.get_texture_from_depth_stencil_if_applicable(image_address))) !!(img = m_rtts.get_texture_from_depth_stencil_if_applicable(image_address)))
{ {
if (img->get_surface_width() != surface_width || if (img->get_surface_width() != surface_width ||
img->get_surface_width() != img->get_surface_height()) img->get_surface_width() != img->get_surface_height())
{ {
can_cast = false; safe_cast = false;
break;
}
image_address += image_size;
image_array[n] = img->get_surface();
} }
else else
{ {
can_cast = false; image_array[n] = img->get_surface();
break;
} }
} }
else
{
safe_cast = false;
}
if (can_cast) image_address += image_size;
}
if (!safe_cast)
{ {
sampled_image_descriptor desc = { texptr->get_surface(), texaddr, format, 0, 0, surface_width, surface_height, texture_upload_context::framebuffer_storage, //TODO: Lower to warning
is_depth, 1.f, 1.f, rsx::texture_dimension_extended::texture_dimension_cubemap }; //TODO: Gather remaining sides from the texture cache or upload from cpu (too slow?)
LOG_ERROR(RSX, "Could not gather all required surfaces for cubemap generation");
}
sampled_image_descriptor desc = { texptr->get_surface(), texaddr, format, 0, 0, rsx::apply_resolution_scale(surface_width, true),
rsx::apply_resolution_scale(surface_height, true), texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
rsx::texture_dimension_extended::texture_dimension_cubemap };
desc.set_external_cubemap_resources(image_array); desc.set_external_cubemap_resources(image_array);
return desc; return desc;
} }
}
LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension); LOG_ERROR(RSX, "Texture resides in render target memory, but requested type is not 2D (%d)", (u32)extended_dimension);
} }

View file

@ -663,10 +663,13 @@ namespace gl
glGetError(); glGetError();
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
{
if (sources[i] != 0)
{ {
glCopyImageSubData(sources[i], GL_TEXTURE_2D, 0, 0, 0, 0, glCopyImageSubData(sources[i], GL_TEXTURE_2D, 0, 0, 0, 0,
dst_id, GL_TEXTURE_CUBE_MAP, 0, 0, 0, i, size, size, 1); dst_id, GL_TEXTURE_CUBE_MAP, 0, 0, 0, i, size, size, 1);
} }
}
m_temporary_surfaces.push_back(dst_id); m_temporary_surfaces.push_back(dst_id);

View file

@ -547,6 +547,8 @@ namespace vk
subresource_range.layerCount = 1; subresource_range.layerCount = 1;
} }
if (sources[n])
{
VkImageLayout old_src_layout = sources[n]->current_layout; VkImageLayout old_src_layout = sources[n]->current_layout;
vk::change_image_layout(cmd, sources[n], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range); vk::change_image_layout(cmd, sources[n], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
@ -560,6 +562,15 @@ namespace vk
vkCmdCopyImage(cmd, sources[n]->value, sources[n]->current_layout, image->value, image->current_layout, 1, &copy_rgn); vkCmdCopyImage(cmd, sources[n]->value, sources[n]->current_layout, image->value, image->current_layout, 1, &copy_rgn);
vk::change_image_layout(cmd, sources[n], old_src_layout, subresource_range); vk::change_image_layout(cmd, sources[n], old_src_layout, subresource_range);
} }
else
{
//Clear to black
VkClearColorValue clear_color{};
auto range = subresource_range;
range.baseArrayLayer = n;
vkCmdClearColorImage(cmd, image->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &range);
}
}
subresource_range.layerCount = 6; subresource_range.layerCount = 6;
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range); vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);