renderer_vulkan: Apply dynamic state
This commit is contained in:
@ -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{
|
||||||
|
@ -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,
|
||||||
|
@ -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++) {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
Reference in New Issue
Block a user