VK renderer: Add Display VRAM core option support

This commit is contained in:
ggdrt 2020-02-11 11:11:27 -08:00
parent e3e511be78
commit fe3cb3394e
5 changed files with 137 additions and 6 deletions

View File

@ -4119,8 +4119,6 @@ bool retro_load_game(const struct retro_game_info *info)
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(wireframe);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(display_vram);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = BEETLE_OPT(image_offset);
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);

View File

@ -195,10 +195,12 @@ struct retro_core_option_definition option_defs_us[] = {
},
"disabled"
},
#endif
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(HAVE_VULKAN)
{
BEETLE_OPT(display_vram),
"Display Full VRAM (Debug)",
"When enabled, visualises the entire emulated console's VRAM. Only supported by the OpenGL hardware renderer. Note: This is for debugging purposes, and should normally be disabled.",
"When enabled, visualises the entire emulated console's VRAM. Only supported by the OpenGL and Vulkan hardware renderers. Note: This is for debugging purposes, and should normally be disabled.",
{
{ "disabled", NULL },
{ "enabled", NULL },

View File

@ -766,6 +766,115 @@ Renderer::DisplayRect Renderer::compute_display_rect()
return DisplayRect(left_offset, upper_offset, display_width, display_height);
}
ImageHandle Renderer::scanout_vram_to_texture(bool scaled)
{
// Like scanout_to_texture(), but synchronizes the entire
// VRAM framebuffer atlas before scanout. Does not apply
// any scanout filters and currently outputs at 15-bit
// color depth. Current implementation does not reuse
// prior scanouts.
atlas.flush_render_pass();
#if 0
if (last_scanout)
return last_scanout;
#endif
Rect vram_rect = {0, 0, FB_WIDTH, FB_HEIGHT};
if (scaled)
atlas.read_fragment(Domain::Scaled, vram_rect);
else
atlas.read_fragment(Domain::Unscaled, vram_rect);
ensure_command_buffer();
if (scanout_semaphore)
{
flush();
device.add_wait_semaphore(CommandBuffer::Type::Generic, scanout_semaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, true);
scanout_semaphore.reset();
}
ensure_command_buffer();
unsigned render_scale = scaled ? scaling : 1;
auto info = ImageCreateInfo::render_target(
FB_WIDTH * render_scale,
FB_HEIGHT * render_scale,
VK_FORMAT_A1R5G5B5_UNORM_PACK16); // Default to 15bit color for now
#if 0
if (!reuseable_scanout ||
reuseable_scanout->get_create_info().width != info.width ||
reuseable_scanout->get_create_info().height != info.height ||
reuseable_scanout->get_create_info().format != info.format)
{
info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
reuseable_scanout = device.create_image(info);
}
#else
info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
reuseable_scanout = device.create_image(info);
#endif
RenderPassInfo rp;
rp.color_attachments[0] = &reuseable_scanout->get_view();
rp.num_color_attachments = 1;
rp.store_attachments = 1;
rp.clear_color[0] = {0, 0, 0, 0};
rp.clear_attachments = 1;
cmd->image_barrier(*reuseable_scanout, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
cmd->begin_render_pass(rp);
cmd->set_quad_state();
cmd->set_program(*pipelines.scaled_quad_blitter);
cmd->set_texture(0, 0, *scaled_views[0], StockSampler::LinearClamp);
cmd->set_vertex_binding(0, *quad, 0, 2);
struct Push
{
float offset[2];
float scale[2];
float uv_min[2];
float uv_max[2];
float max_bias;
};
Push push = { { float(vram_rect.x) / FB_WIDTH, float(vram_rect.y) / FB_HEIGHT },
{ float(vram_rect.width) / FB_WIDTH, float(vram_rect.height) / FB_HEIGHT },
{ (vram_rect.x + 0.5f) / FB_WIDTH, (vram_rect.y + 0.5f) / FB_HEIGHT },
{ (vram_rect.x + vram_rect.width - 0.5f) / FB_WIDTH, (vram_rect.y + vram_rect.height - 0.5f) / FB_HEIGHT },
float(scaled_views.size() - 1) };
cmd->push_constants(&push, 0, sizeof(push));
cmd->set_vertex_attrib(0, 0, VK_FORMAT_R8G8_SNORM, 0);
cmd->set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
counters.draw_calls++;
counters.vertices += 4;
cmd->draw(4);
cmd->end_render_pass();
cmd->image_barrier(*reuseable_scanout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT);
last_scanout = reuseable_scanout;
return reuseable_scanout;
}
ImageHandle Renderer::scanout_to_texture()
{
atlas.flush_render_pass();

View File

@ -268,6 +268,7 @@ public:
void scanout();
Vulkan::BufferHandle scanout_to_buffer(bool draw_area, unsigned &width, unsigned &height);
Vulkan::BufferHandle scanout_vram_to_buffer(unsigned &width, unsigned &height);
Vulkan::ImageHandle scanout_vram_to_texture(bool scaled = true);
Vulkan::ImageHandle scanout_to_texture();
inline void set_texture_mode(TextureMode mode)

View File

@ -60,6 +60,7 @@ static int last_scanline_pal;
static bool frame_duping_enabled = false;
static uint32_t prev_frame_width = 320;
static uint32_t prev_frame_height = 240;
static bool show_vram = false;
static retro_video_refresh_t video_refresh_cb;
@ -205,7 +206,13 @@ void rsx_vulkan_get_system_av_info(struct retro_system_av_info *info)
info->geometry.max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H * (super_sampling ? 1 : scaling);
info->timing.sample_rate = SOUND_FREQUENCY;
info->geometry.aspect_ratio = !widescreen_hack ? MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO : 16.0 / 9.0;
if (show_vram)
info->geometry.aspect_ratio = 2.0 / 1.0;
else if (widescreen_hack)
info->geometry.aspect_ratio = 16.0 / 9.0;
else
info->geometry.aspect_ratio = MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO;
if (content_is_pal)
info->timing.fps = FPS_PAL_NONINTERLACED;
else
@ -232,6 +239,7 @@ void rsx_vulkan_refresh_variables(void)
unsigned old_scaling = scaling;
unsigned old_msaa = msaa;
bool old_super_sampling = super_sampling;
bool old_show_vram = show_vram;
var.key = BEETLE_OPT(internal_resolution);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@ -353,8 +361,21 @@ void rsx_vulkan_refresh_variables(void)
frame_duping_enabled = false;
}
var.key = BEETLE_OPT(display_vram);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "enabled"))
show_vram = true;
else
show_vram = false;
}
// Changing crop_overscan and scanlines will likely need to be included here in future geometry fixes
if ((old_scaling != scaling || old_super_sampling != super_sampling || old_msaa != msaa) && renderer)
if ((old_scaling != scaling ||
old_super_sampling != super_sampling ||
old_msaa != msaa ||
old_show_vram != show_vram)
&& renderer)
{
retro_system_av_info info;
rsx_vulkan_get_system_av_info(&info);
@ -415,7 +436,7 @@ void rsx_vulkan_finalize_frame(const void *fb, unsigned width,
else
renderer->set_display_filter(super_sampling ? Renderer::ScanoutFilter::SSAA : Renderer::ScanoutFilter::None);
auto scanout = renderer->scanout_to_texture();
auto scanout = show_vram ? renderer->scanout_vram_to_texture() : renderer->scanout_to_texture();
retro_vulkan_image *image = &swapchain_image;