renderer_vulkan: Apply dynamic state

This commit is contained in:
emufan4568
2022-08-14 09:37:09 +03:00
parent be90677180
commit 2d27a19a45
6 changed files with 81 additions and 7 deletions

View File

@ -9,7 +9,7 @@
#include "common/common_types.h" #include "common/common_types.h"
// defined in Version.cpp // defined in Version.cpp
extern const char* scm_rev_git_str; const char* scm_rev_git_str = "DUMMY";
// On disk format: // On disk format:
// header{ // header{

View File

@ -656,6 +656,7 @@ bool Rasterizer::Draw(bool accelerate, bool is_indexed) {
// Sync the viewport // Sync the viewport
PipelineHandle raster_pipeline = pipeline_cache->GetPipeline(raster_info); 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, raster_pipeline->SetViewport(surfaces_rect.left + viewport_rect_unscaled.left * res_scale,
surfaces_rect.bottom + viewport_rect_unscaled.bottom * res_scale, surfaces_rect.bottom + viewport_rect_unscaled.bottom * res_scale,
viewport_rect_unscaled.GetWidth() * res_scale, viewport_rect_unscaled.GetWidth() * res_scale,

View File

@ -4,6 +4,8 @@
#define VULKAN_HPP_NO_CONSTRUCTORS #define VULKAN_HPP_NO_CONSTRUCTORS
#include <functional> #include <functional>
#include "common/file_util.h"
#include "common/linear_disk_cache.h"
#include "core/core.h" #include "core/core.h"
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
#include "video_core/renderer_vulkan/vk_backend.h" #include "video_core/renderer_vulkan/vk_backend.h"
@ -42,6 +44,28 @@ constexpr vk::IndexType ToVkIndexType(AttribType type) {
} }
} }
class PipelineCacheReadCallback : public LinearDiskCacheReader<u32, u8>
{
public:
PipelineCacheReadCallback(std::vector<u8>* 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<u8>* m_data;
};
class PipelineCacheReadIgnoreCallback : public LinearDiskCacheReader<u32, u8>
{
public:
void Read(const u32& key, const u8* value, u32 value_size) override {}
};
Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window), Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window),
instance(window), scheduler(instance, pool_manager), renderpass_cache(instance), instance(window), scheduler(instance, pool_manager), renderpass_cache(instance),
swapchain(instance, scheduler, renderpass_cache, pool_manager, instance.GetSurface()) { 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_Model", "GTX 1650");
telemetry_session.AddField(user_system, "GPU_Vulkan_Version", "Vulkan 1.3"); telemetry_session.AddField(user_system, "GPU_Vulkan_Version", "Vulkan 1.3");
vk::PipelineCacheCreateInfo cache_info{};
std::vector<u8> disk_data;
LinearDiskCache<u32, u8> 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 // Create pipeline cache object
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
pipeline_cache = device.createPipelineCache({}); pipeline_cache = device.createPipelineCache(cache_info);
constexpr std::array pool_sizes = { constexpr std::array pool_sizes = {
vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 1024}, vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 1024},
@ -81,11 +122,24 @@ Backend::Backend(Frontend::EmuWindow& window) : BackendBase(window),
} }
Backend::~Backend() { Backend::~Backend() {
// Wait for all GPU operations to finish before continuing // Wait for all GPU operations to finish before continuing
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
device.waitIdle(); 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<u32, u8> disk_cache;
PipelineCacheReadIgnoreCallback callback;
disk_cache.OpenAndRead(pipeline_cache_filename.c_str(), callback);
disk_cache.Append(1, data.data(), static_cast<u32>(data.size()));
disk_cache.Close();
device.destroyPipelineCache(pipeline_cache); device.destroyPipelineCache(pipeline_cache);
for (u32 pool = 0; pool < SCHEDULER_COMMAND_COUNT; pool++) { for (u32 pool = 0; pool < SCHEDULER_COMMAND_COUNT; pool++) {

View File

@ -70,8 +70,9 @@ private:
CommandScheduler scheduler; CommandScheduler scheduler;
RenderpassCache renderpass_cache; RenderpassCache renderpass_cache;
Swapchain swapchain; Swapchain swapchain;
vk::PipelineCache pipeline_cache;
vk::PipelineCache pipeline_cache;
std::string pipeline_cache_filename = "pipeline_cache.bin";
std::unordered_map<u64, std::unique_ptr<PipelineOwner>, Common::IdentityHash> pipeline_owners; std::unordered_map<u64, std::unique_ptr<PipelineOwner>, Common::IdentityHash> pipeline_owners;
std::array<vk::DescriptorPool, SCHEDULER_COMMAND_COUNT> descriptor_pools; std::array<vk::DescriptorPool, SCHEDULER_COMMAND_COUNT> descriptor_pools;
//FramebufferHandle current_framebuffer; //FramebufferHandle current_framebuffer;

View File

@ -459,7 +459,25 @@ void Pipeline::SetScissor(s32 x, s32 y, u32 width, u32 height) {
} }
void Pipeline::ApplyDynamic(const PipelineInfo& info) { 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 } // namespace VideoCore::Vulkan

View File

@ -271,7 +271,7 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32
const std::array offsets = { const std::array offsets = {
vk::Offset3D{rectangle.x, rectangle.y, 0}, vk::Offset3D{rectangle.x, rectangle.y, 0},
vk::Offset3D{static_cast<s32>(rectangle.x + rectangle.width), vk::Offset3D{static_cast<s32>(rectangle.x + rectangle.width),
static_cast<s32>(rectangle.y + rectangle.height), 0} static_cast<s32>(rectangle.y + rectangle.height), 1}
}; };
const vk::ImageBlit image_blit = { const vk::ImageBlit image_blit = {
@ -525,7 +525,7 @@ void Texture::BlitTo(TextureHandle dest, Common::Rectangle<u32> source_rect, Com
command_buffer.blitImage(image, vk::ImageLayout::eTransferSrcOptimal, command_buffer.blitImage(image, vk::ImageLayout::eTransferSrcOptimal,
dest_texture->GetHandle(), vk::ImageLayout::eTransferDstOptimal, dest_texture->GetHandle(), vk::ImageLayout::eTransferDstOptimal,
blit_area, vk::Filter::eNearest); blit_area, vk::Filter::eLinear);
// Prepare for shader reads // Prepare for shader reads
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal); Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal);
@ -663,7 +663,7 @@ StagingTexture::StagingTexture(Instance& instance, CommandScheduler& scheduler,
.oldLayout = vk::ImageLayout::eUndefined, .oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eGeneral, .newLayout = vk::ImageLayout::eGeneral,
.image = image, .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(); vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();