early-access version 1930

This commit is contained in:
pineappleEA 2021-07-27 20:26:47 +02:00
parent 6ecaf46441
commit ed874dd126
8 changed files with 8 additions and 109 deletions

View File

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 1929. This is the source code for early-access 1930.
## Legal Notice ## Legal Notice

View File

@ -27,7 +27,7 @@ void RendererBase::UpdateCurrentFramebufferLayout() {
render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height); render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
} }
void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callback, void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
const Layout::FramebufferLayout& layout) { const Layout::FramebufferLayout& layout) {
if (renderer_settings.screenshot_requested) { if (renderer_settings.screenshot_requested) {
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request"); LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");

View File

@ -24,7 +24,7 @@ struct RendererSettings {
// Screenshot // Screenshot
std::atomic<bool> screenshot_requested{false}; std::atomic<bool> screenshot_requested{false};
void* screenshot_bits{}; void* screenshot_bits{};
std::function<void(bool)> screenshot_complete_callback; std::function<void()> screenshot_complete_callback;
Layout::FramebufferLayout screenshot_framebuffer_layout; Layout::FramebufferLayout screenshot_framebuffer_layout;
}; };
@ -80,7 +80,7 @@ public:
void RefreshBaseSettings(); void RefreshBaseSettings();
/// Request a screenshot of the next frame /// Request a screenshot of the next frame
void RequestScreenshot(void* data, std::function<void(bool)> callback, void RequestScreenshot(void* data, std::function<void()> callback,
const Layout::FramebufferLayout& layout); const Layout::FramebufferLayout& layout);
protected: protected:

View File

@ -486,7 +486,7 @@ void RendererOpenGL::RenderScreenshot() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
renderer_settings.screenshot_complete_callback(true); renderer_settings.screenshot_complete_callback();
renderer_settings.screenshot_requested = false; renderer_settings.screenshot_requested = false;
} }

View File

@ -165,7 +165,6 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated); const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated);
scheduler.Flush(render_semaphore); scheduler.Flush(render_semaphore);
scheduler.WaitWorker(); scheduler.WaitWorker();
RenderScreenshot();
swapchain.Present(render_semaphore); swapchain.Present(render_semaphore);
gpu.RendererFrameEndNotify(); gpu.RendererFrameEndNotify();
@ -194,102 +193,4 @@ void RendererVulkan::Report() const {
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
} }
void Vulkan::RendererVulkan::RenderScreenshot() {
if (!renderer_settings.screenshot_requested) {
return;
}
const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
const auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4);
const VkBufferCreateInfo dst_info{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = buffer_size,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
};
const VkImage src_image = swapchain.GetImageIndex(swapchain.GetImageIndex());
const vk::Buffer dst_buffer = device.GetLogical().CreateBuffer(dst_info);
MemoryCommit dst_memory = memory_allocator.Commit(dst_buffer, MemoryUsage::Download);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([buffer = *dst_buffer, src_image, layout](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
const VkImageMemoryBarrier image_write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
static constexpr VkMemoryBarrier memory_write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
};
const VkBufferImageCopy copy{
.bufferOffset = 0,
.bufferRowLength = layout.width,
.bufferImageHeight = layout.height,
.imageSubresource{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset{.x = 0, .y = 0, .z = 0},
.imageExtent{
.width = layout.width,
.height = layout.height,
.depth = 1,
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, read_barrier);
cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
0, memory_write_barrier, nullptr, image_write_barrier);
});
// Ensure the copy is fully completed before saving the screenshot
scheduler.Finish();
// Copy backing image data to the QImage screenshot buffer
std::memcpy(renderer_settings.screenshot_bits, dst_memory.Map().data(),
dst_memory.Map().size());
renderer_settings.screenshot_complete_callback(false);
renderer_settings.screenshot_requested = false;
}
} // namespace Vulkan } // namespace Vulkan

View File

@ -54,8 +54,6 @@ public:
private: private:
void Report() const; void Report() const;
void RenderScreenshot();
Core::TelemetrySession& telemetry_session; Core::TelemetrySession& telemetry_session;
Core::Memory::Memory& cpu_memory; Core::Memory::Memory& cpu_memory;
Tegra::GPU& gpu; Tegra::GPU& gpu;

View File

@ -202,7 +202,7 @@ void SetObjectName(const DeviceDispatch* dld, VkDevice device, T handle, VkObjec
const VkDebugUtilsObjectNameInfoEXT name_info{ const VkDebugUtilsObjectNameInfoEXT name_info{
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
.pNext = nullptr, .pNext = nullptr,
.objectType = VK_OBJECT_TYPE_IMAGE, .objectType = type,
.objectHandle = reinterpret_cast<u64>(handle), .objectHandle = reinterpret_cast<u64>(handle),
.pObjectName = name, .pObjectName = name,
}; };

View File

@ -634,9 +634,9 @@ void GRenderWindow::CaptureScreenshot(u32 res_scale, const QString& screenshot_p
screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32); screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32);
renderer.RequestScreenshot( renderer.RequestScreenshot(
screenshot_image.bits(), screenshot_image.bits(),
[=, this](bool invert_y) { [=, this] {
const std::string std_screenshot_path = screenshot_path.toStdString(); const std::string std_screenshot_path = screenshot_path.toStdString();
if (screenshot_image.mirrored(false, invert_y).save(screenshot_path)) { if (screenshot_image.mirrored(false, true).save(screenshot_path)) {
LOG_INFO(Frontend, "Screenshot saved to \"{}\"", std_screenshot_path); LOG_INFO(Frontend, "Screenshot saved to \"{}\"", std_screenshot_path);
} else { } else {
LOG_ERROR(Frontend, "Failed to save screenshot to \"{}\"", std_screenshot_path); LOG_ERROR(Frontend, "Failed to save screenshot to \"{}\"", std_screenshot_path);