renderer_vulkan: Apply dynamic state
This commit is contained in:
@ -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{
|
||||
|
@ -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,
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#define VULKAN_HPP_NO_CONSTRUCTORS
|
||||
#include <functional>
|
||||
#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<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),
|
||||
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<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
|
||||
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<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);
|
||||
|
||||
for (u32 pool = 0; pool < SCHEDULER_COMMAND_COUNT; pool++) {
|
||||
|
@ -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<u64, std::unique_ptr<PipelineOwner>, Common::IdentityHash> pipeline_owners;
|
||||
std::array<vk::DescriptorPool, SCHEDULER_COMMAND_COUNT> descriptor_pools;
|
||||
//FramebufferHandle current_framebuffer;
|
||||
|
@ -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
|
||||
|
@ -271,7 +271,7 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32
|
||||
const std::array offsets = {
|
||||
vk::Offset3D{rectangle.x, rectangle.y, 0},
|
||||
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 = {
|
||||
@ -525,7 +525,7 @@ void Texture::BlitTo(TextureHandle dest, Common::Rectangle<u32> 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();
|
||||
|
Reference in New Issue
Block a user