From 2d27a19a4552af73beb1c05976e3125f23bbdedf Mon Sep 17 00:00:00 2001 From: emufan4568 Date: Sun, 14 Aug 2022 09:37:09 +0300 Subject: [PATCH] renderer_vulkan: Apply dynamic state --- src/common/linear_disk_cache.h | 2 +- src/video_core/common/rasterizer.cpp | 1 + src/video_core/renderer_vulkan/vk_backend.cpp | 58 ++++++++++++++++++- src/video_core/renderer_vulkan/vk_backend.h | 3 +- .../renderer_vulkan/vk_pipeline.cpp | 18 ++++++ src/video_core/renderer_vulkan/vk_texture.cpp | 6 +- 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h index 61e4bd217..d1ab5babd 100644 --- a/src/common/linear_disk_cache.h +++ b/src/common/linear_disk_cache.h @@ -9,7 +9,7 @@ #include "common/common_types.h" // defined in Version.cpp -extern const char* scm_rev_git_str; +const char* scm_rev_git_str = "DUMMY"; // On disk format: // header{ diff --git a/src/video_core/common/rasterizer.cpp b/src/video_core/common/rasterizer.cpp index 83d6d26a6..46b7d6b4b 100644 --- a/src/video_core/common/rasterizer.cpp +++ b/src/video_core/common/rasterizer.cpp @@ -656,6 +656,7 @@ bool Rasterizer::Draw(bool accelerate, bool is_indexed) { // Sync the viewport PipelineHandle raster_pipeline = pipeline_cache->GetPipeline(raster_info); + raster_pipeline->ApplyDynamic(raster_info); raster_pipeline->SetViewport(surfaces_rect.left + viewport_rect_unscaled.left * res_scale, surfaces_rect.bottom + viewport_rect_unscaled.bottom * res_scale, viewport_rect_unscaled.GetWidth() * res_scale, diff --git a/src/video_core/renderer_vulkan/vk_backend.cpp b/src/video_core/renderer_vulkan/vk_backend.cpp index 4d542d95e..1a21cf128 100644 --- a/src/video_core/renderer_vulkan/vk_backend.cpp +++ b/src/video_core/renderer_vulkan/vk_backend.cpp @@ -4,6 +4,8 @@ #define VULKAN_HPP_NO_CONSTRUCTORS #include +#include "common/file_util.h" +#include "common/linear_disk_cache.h" #include "core/core.h" #include "core/frontend/emu_window.h" #include "video_core/renderer_vulkan/vk_backend.h" @@ -42,6 +44,28 @@ constexpr vk::IndexType ToVkIndexType(AttribType type) { } } +class PipelineCacheReadCallback : public LinearDiskCacheReader +{ +public: + PipelineCacheReadCallback(std::vector* data) : m_data(data) {} + void Read(const u32& key, const u8* value, u32 value_size) override + { + m_data->resize(value_size); + if (value_size > 0) + memcpy(m_data->data(), value, value_size); + } + +private: + std::vector* m_data; +}; + +class PipelineCacheReadIgnoreCallback : public LinearDiskCacheReader +{ +public: + void Read(const u32& key, const u8* value, u32 value_size) override {} +}; + + Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window), instance(window), scheduler(instance, pool_manager), renderpass_cache(instance), swapchain(instance, scheduler, renderpass_cache, pool_manager, instance.GetSurface()) { @@ -53,9 +77,26 @@ Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window), telemetry_session.AddField(user_system, "GPU_Model", "GTX 1650"); telemetry_session.AddField(user_system, "GPU_Vulkan_Version", "Vulkan 1.3"); + vk::PipelineCacheCreateInfo cache_info{}; + + std::vector disk_data; + LinearDiskCache disk_cache; + PipelineCacheReadCallback read_callback(&disk_data); + if (disk_cache.OpenAndRead(pipeline_cache_filename.c_str(), read_callback) != 1) { + disk_data.clear(); + } + + if (!disk_data.empty()) { + // Don't use this data. In fact, we should delete it to prevent it from being used next time. + FileUtil::Delete(pipeline_cache_filename); + } else { + cache_info.initialDataSize = disk_data.size(); + cache_info.pInitialData = disk_data.data(); + } + // Create pipeline cache object vk::Device device = instance.GetDevice(); - pipeline_cache = device.createPipelineCache({}); + pipeline_cache = device.createPipelineCache(cache_info); constexpr std::array pool_sizes = { vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 1024}, @@ -81,11 +122,24 @@ Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window), } Backend::~Backend() { - // Wait for all GPU operations to finish before continuing vk::Device device = instance.GetDevice(); device.waitIdle(); + auto data = device.getPipelineCacheData(pipeline_cache); + + // Delete the old cache and re-create. + FileUtil::Delete(pipeline_cache_filename); + + // We write a single key of 1, with the entire pipeline cache data. + // Not ideal, but our disk cache class does not support just writing a single blob + // of data without specifying a key. + LinearDiskCache disk_cache; + PipelineCacheReadIgnoreCallback callback; + disk_cache.OpenAndRead(pipeline_cache_filename.c_str(), callback); + disk_cache.Append(1, data.data(), static_cast(data.size())); + disk_cache.Close(); + device.destroyPipelineCache(pipeline_cache); for (u32 pool = 0; pool < SCHEDULER_COMMAND_COUNT; pool++) { diff --git a/src/video_core/renderer_vulkan/vk_backend.h b/src/video_core/renderer_vulkan/vk_backend.h index 3fd922774..1ac411e4e 100644 --- a/src/video_core/renderer_vulkan/vk_backend.h +++ b/src/video_core/renderer_vulkan/vk_backend.h @@ -70,8 +70,9 @@ private: CommandScheduler scheduler; RenderpassCache renderpass_cache; Swapchain swapchain; - vk::PipelineCache pipeline_cache; + vk::PipelineCache pipeline_cache; + std::string pipeline_cache_filename = "pipeline_cache.bin"; std::unordered_map, Common::IdentityHash> pipeline_owners; std::array descriptor_pools; //FramebufferHandle current_framebuffer; diff --git a/src/video_core/renderer_vulkan/vk_pipeline.cpp b/src/video_core/renderer_vulkan/vk_pipeline.cpp index b17d7a99c..281e29ebc 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline.cpp @@ -459,7 +459,25 @@ void Pipeline::SetScissor(s32 x, s32 y, u32 width, u32 height) { } void Pipeline::ApplyDynamic(const PipelineInfo& info) { + vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); + command_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, info.depth_stencil.stencil_compare_mask); + command_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, info.depth_stencil.stencil_write_mask); + command_buffer.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, info.depth_stencil.stencil_reference); + if (instance.IsExtendedDynamicStateSupported()) { + command_buffer.setCullModeEXT(PicaToVK::CullMode(info.rasterization.cull_mode)); + command_buffer.setDepthCompareOpEXT(PicaToVK::CompareFunc(info.depth_stencil.depth_compare_op)); + command_buffer.setDepthTestEnableEXT(info.depth_stencil.depth_test_enable); + command_buffer.setDepthWriteEnableEXT(info.depth_stencil.depth_write_enable); + command_buffer.setFrontFaceEXT(PicaToVK::FrontFace(info.rasterization.cull_mode)); + command_buffer.setPrimitiveTopologyEXT(PicaToVK::PrimitiveTopology(info.rasterization.topology)); + command_buffer.setStencilTestEnableEXT(info.depth_stencil.stencil_test_enable); + command_buffer.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, + PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op), + PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op), + PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_op), + PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op)); + } } } // namespace VideoCore::Vulkan diff --git a/src/video_core/renderer_vulkan/vk_texture.cpp b/src/video_core/renderer_vulkan/vk_texture.cpp index 796d42f86..78a25834b 100644 --- a/src/video_core/renderer_vulkan/vk_texture.cpp +++ b/src/video_core/renderer_vulkan/vk_texture.cpp @@ -271,7 +271,7 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span data, u32 const std::array offsets = { vk::Offset3D{rectangle.x, rectangle.y, 0}, vk::Offset3D{static_cast(rectangle.x + rectangle.width), - static_cast(rectangle.y + rectangle.height), 0} + static_cast(rectangle.y + rectangle.height), 1} }; const vk::ImageBlit image_blit = { @@ -525,7 +525,7 @@ void Texture::BlitTo(TextureHandle dest, Common::Rectangle source_rect, Com command_buffer.blitImage(image, vk::ImageLayout::eTransferSrcOptimal, dest_texture->GetHandle(), vk::ImageLayout::eTransferDstOptimal, - blit_area, vk::Filter::eNearest); + blit_area, vk::Filter::eLinear); // Prepare for shader reads Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal); @@ -663,7 +663,7 @@ StagingTexture::StagingTexture(Instance& instance, CommandScheduler& scheduler, .oldLayout = vk::ImageLayout::eUndefined, .newLayout = vk::ImageLayout::eGeneral, .image = image, - .subresourceRange = {vk::ImageAspectFlagBits::eColor, 0, info.levels, 0, 1} + .subresourceRange = {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1} }; vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();