video: Import new shader recompiler + display a triangle (#142)

This commit is contained in:
TheTurtle 2024-05-22 01:35:12 +03:00 committed by GitHub
parent 8cf64a33b2
commit 8730968385
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
103 changed files with 17793 additions and 729 deletions

View file

@ -0,0 +1,113 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
namespace Vulkan::LiverpoolToVK {
vk::StencilOp StencilOp(Liverpool::StencilFunc op) {
switch (op) {
case Liverpool::StencilFunc::Keep:
return vk::StencilOp::eKeep;
case Liverpool::StencilFunc::Zero:
return vk::StencilOp::eZero;
case Liverpool::StencilFunc::AddClamp:
return vk::StencilOp::eIncrementAndClamp;
case Liverpool::StencilFunc::SubClamp:
return vk::StencilOp::eDecrementAndClamp;
case Liverpool::StencilFunc::Invert:
return vk::StencilOp::eInvert;
case Liverpool::StencilFunc::AddWrap:
return vk::StencilOp::eIncrementAndWrap;
case Liverpool::StencilFunc::SubWrap:
return vk::StencilOp::eDecrementAndWrap;
default:
UNREACHABLE();
return vk::StencilOp::eKeep;
}
}
vk::CompareOp CompareOp(Liverpool::CompareFunc func) {
switch (func) {
case Liverpool::CompareFunc::Always:
return vk::CompareOp::eAlways;
case Liverpool::CompareFunc::Equal:
return vk::CompareOp::eEqual;
case Liverpool::CompareFunc::GreaterEqual:
return vk::CompareOp::eGreaterOrEqual;
case Liverpool::CompareFunc::Greater:
return vk::CompareOp::eGreater;
case Liverpool::CompareFunc::LessEqual:
return vk::CompareOp::eLessOrEqual;
case Liverpool::CompareFunc::Less:
return vk::CompareOp::eLess;
case Liverpool::CompareFunc::NotEqual:
return vk::CompareOp::eNotEqual;
case Liverpool::CompareFunc::Never:
return vk::CompareOp::eNever;
default:
UNREACHABLE();
return vk::CompareOp::eAlways;
}
}
vk::PrimitiveTopology PrimitiveType(Liverpool::PrimitiveType type) {
switch (type) {
case Liverpool::PrimitiveType::PointList:
return vk::PrimitiveTopology::ePointList;
case Liverpool::PrimitiveType::LineList:
return vk::PrimitiveTopology::eLineList;
case Liverpool::PrimitiveType::LineStrip:
return vk::PrimitiveTopology::eLineStrip;
case Liverpool::PrimitiveType::TriangleList:
return vk::PrimitiveTopology::eTriangleList;
case Liverpool::PrimitiveType::TriangleFan:
return vk::PrimitiveTopology::eTriangleFan;
case Liverpool::PrimitiveType::TriangleStrip:
return vk::PrimitiveTopology::eTriangleStrip;
case Liverpool::PrimitiveType::AdjLineList:
return vk::PrimitiveTopology::eLineListWithAdjacency;
case Liverpool::PrimitiveType::AdjLineStrip:
return vk::PrimitiveTopology::eLineStripWithAdjacency;
case Liverpool::PrimitiveType::AdjTriangleList:
return vk::PrimitiveTopology::eTriangleListWithAdjacency;
case Liverpool::PrimitiveType::AdjTriangleStrip:
return vk::PrimitiveTopology::eTriangleStripWithAdjacency;
default:
UNREACHABLE();
return vk::PrimitiveTopology::eTriangleList;
}
}
vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode) {
switch (mode) {
case Liverpool::PolygonMode::Point:
return vk::PolygonMode::ePoint;
case Liverpool::PolygonMode::Line:
return vk::PolygonMode::eLine;
case Liverpool::PolygonMode::Fill:
return vk::PolygonMode::eFill;
default:
UNREACHABLE();
return vk::PolygonMode::eFill;
}
}
vk::CullModeFlags CullMode(Liverpool::CullMode mode) {
switch (mode) {
case Liverpool::CullMode::None:
return vk::CullModeFlagBits::eNone;
case Liverpool::CullMode::Front:
return vk::CullModeFlagBits::eFront;
case Liverpool::CullMode::Back:
return vk::CullModeFlagBits::eBack;
case Liverpool::CullMode::FrontAndBack:
return vk::CullModeFlagBits::eFrontAndBack;
default:
UNREACHABLE();
return vk::CullModeFlagBits::eNone;
}
}
} // namespace Vulkan::LiverpoolToVK

View file

@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_common.h"
namespace Vulkan::LiverpoolToVK {
using Liverpool = AmdGpu::Liverpool;
vk::StencilOp StencilOp(Liverpool::StencilFunc op);
vk::CompareOp CompareOp(Liverpool::CompareFunc func);
vk::PrimitiveTopology PrimitiveType(Liverpool::PrimitiveType type);
vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode);
vk::CullModeFlags CullMode(Liverpool::CullMode mode);
} // namespace Vulkan::LiverpoolToVK

View file

@ -7,6 +7,7 @@
#include "core/libraries/system/systemservice.h"
#include "sdl_window.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include <vk_mem_alloc.h>
@ -60,9 +61,10 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
};
}
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_)
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool)
: window{window_}, instance{window, Config::getGpuId()}, scheduler{instance},
swapchain{instance, window}, texture_cache{instance, scheduler} {
rasterizer = std::make_unique<Rasterizer>(instance, scheduler, texture_cache, liverpool);
const u32 num_images = swapchain.GetImageCount();
const vk::Device device = instance.GetDevice();

View file

@ -13,6 +13,10 @@ namespace Frontend {
class WindowSDL;
}
namespace AmdGpu {
struct Liverpool;
}
namespace Vulkan {
struct Frame {
@ -26,9 +30,11 @@ struct Frame {
vk::CommandBuffer cmdbuf;
};
class Rasterizer;
class RendererVulkan {
public:
explicit RendererVulkan(Frontend::WindowSDL& window);
explicit RendererVulkan(Frontend::WindowSDL& window, AmdGpu::Liverpool* liverpool);
~RendererVulkan();
Frame* PrepareFrame(const Libraries::VideoOut::BufferAttributeGroup& attribute,
@ -47,6 +53,7 @@ private:
Instance instance;
Scheduler scheduler;
Swapchain swapchain;
std::unique_ptr<Rasterizer> rasterizer;
VideoCore::TextureCache texture_cache;
vk::UniqueCommandPool command_pool;
std::vector<Frame> present_frames;

View file

@ -0,0 +1,162 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <boost/container/static_vector.hpp>
#include "common/assert.h"
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
#include "video_core/renderer_vulkan/vk_instance.h"
namespace Vulkan {
GraphicsPipeline::GraphicsPipeline(const Instance& instance_, const PipelineKey& key_,
vk::PipelineCache pipeline_cache_, vk::PipelineLayout layout_,
std::array<vk::ShaderModule, MaxShaderStages> modules)
: instance{instance_}, pipeline_layout{layout_}, pipeline_cache{pipeline_cache_}, key{key_} {
const vk::Device device = instance.GetDevice();
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
.vertexBindingDescriptionCount = 0U,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0U,
.pVertexAttributeDescriptions = nullptr,
};
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = LiverpoolToVK::PrimitiveType(key.prim_type),
.primitiveRestartEnable = false,
};
const vk::PipelineRasterizationStateCreateInfo raster_state = {
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
.cullMode = LiverpoolToVK::CullMode(key.cull_mode),
.frontFace = vk::FrontFace::eClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0f,
};
const vk::PipelineMultisampleStateCreateInfo multisampling = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
.blendEnable = false,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = false,
.logicOp = vk::LogicOp::eCopy,
.attachmentCount = 1,
.pAttachments = &colorblend_attachment,
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
};
const vk::Viewport viewport = {
.x = 0.0f,
.y = 0.0f,
.width = 1.0f,
.height = 1.0f,
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
const vk::Rect2D scissor = {
.offset = {0, 0},
.extent = {1, 1},
};
const vk::PipelineViewportStateCreateInfo viewport_info = {
.viewportCount = 1,
.pViewports = &viewport,
.scissorCount = 1,
.pScissors = &scissor,
};
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
vk::DynamicState::eViewport,
vk::DynamicState::eScissor,
};
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data(),
};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthTestEnable = key.depth.depth_enable,
.depthWriteEnable = key.depth.depth_write_enable,
.depthCompareOp = LiverpoolToVK::CompareOp(key.depth.depth_func),
.depthBoundsTestEnable = key.depth.depth_bounds_enable,
.stencilTestEnable = key.depth.stencil_enable,
.front{
.failOp = LiverpoolToVK::StencilOp(key.stencil.stencil_fail_front),
.passOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zpass_front),
.depthFailOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zfail_front),
.compareOp = LiverpoolToVK::CompareOp(key.depth.stencil_ref_func),
.compareMask = key.stencil_ref_front.stencil_mask,
.writeMask = key.stencil_ref_front.stencil_write_mask,
.reference = key.stencil_ref_front.stencil_test_val,
},
.back{
.failOp = LiverpoolToVK::StencilOp(key.stencil.stencil_fail_back),
.passOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zpass_back),
.depthFailOp = LiverpoolToVK::StencilOp(key.stencil.stencil_zfail_back),
.compareOp = LiverpoolToVK::CompareOp(key.depth.stencil_bf_func),
.compareMask = key.stencil_ref_back.stencil_mask,
.writeMask = key.stencil_ref_back.stencil_write_mask,
.reference = key.stencil_ref_back.stencil_test_val,
},
};
u32 shader_count = 2;
std::array<vk::PipelineShaderStageCreateInfo, MaxShaderStages> shader_stages;
shader_stages[0] = vk::PipelineShaderStageCreateInfo{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = modules[0],
.pName = "main",
};
shader_stages[1] = vk::PipelineShaderStageCreateInfo{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = modules[4],
.pName = "main",
};
const vk::Format color_format = vk::Format::eB8G8R8A8Srgb;
const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci = {
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &color_format,
.depthAttachmentFormat = vk::Format::eUndefined,
.stencilAttachmentFormat = vk::Format::eUndefined,
};
const vk::GraphicsPipelineCreateInfo pipeline_info = {
.pNext = &pipeline_rendering_ci,
.stageCount = shader_count,
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input_info,
.pInputAssemblyState = &input_assembly,
.pViewportState = &viewport_info,
.pRasterizationState = &raster_state,
.pMultisampleState = &multisampling,
.pDepthStencilState = &depth_info,
.pColorBlendState = &color_blending,
.pDynamicState = &dynamic_info,
.layout = pipeline_layout,
};
auto result = device.createGraphicsPipelineUnique(pipeline_cache, pipeline_info);
if (result.result == vk::Result::eSuccess) {
pipeline = std::move(result.value);
} else {
UNREACHABLE_MSG("Graphics pipeline creation failed!");
}
}
GraphicsPipeline::~GraphicsPipeline() = default;
} // namespace Vulkan

View file

@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/types.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
#include "video_core/renderer_vulkan/vk_common.h"
namespace Vulkan {
static constexpr u32 MaxShaderStages = 5;
class Instance;
using Liverpool = AmdGpu::Liverpool;
struct PipelineKey {
Liverpool::DepthControl depth;
Liverpool::StencilControl stencil;
Liverpool::StencilRefMask stencil_ref_front;
Liverpool::StencilRefMask stencil_ref_back;
Liverpool::PrimitiveType prim_type;
Liverpool::PolygonMode polygon_mode;
Liverpool::CullMode cull_mode;
};
static_assert(std::has_unique_object_representations_v<PipelineKey>);
class GraphicsPipeline {
public:
explicit GraphicsPipeline(const Instance& instance, const PipelineKey& key,
vk::PipelineCache pipeline_cache, vk::PipelineLayout layout,
std::array<vk::ShaderModule, MaxShaderStages> modules);
~GraphicsPipeline();
[[nodiscard]] vk::Pipeline Handle() const noexcept {
return *pipeline;
}
private:
const Instance& instance;
vk::UniquePipeline pipeline;
vk::PipelineLayout pipeline_layout;
vk::PipelineCache pipeline_cache;
PipelineKey key;
};
} // namespace Vulkan

View file

@ -196,9 +196,15 @@ bool Instance::CreateDevice() {
.shaderClipDistance = features.shaderClipDistance,
},
},
vk::PhysicalDeviceVulkan11Features{
.shaderDrawParameters = true,
},
vk::PhysicalDeviceVulkan12Features{
.timelineSemaphore = true,
},
vk::PhysicalDeviceVulkan13Features{
.dynamicRendering = true,
},
vk::PhysicalDeviceCustomBorderColorFeaturesEXT{
.customBorderColors = true,
.customBorderColorWithoutFormat = true,

View file

@ -0,0 +1,70 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "shader_recompiler/recompiler.h"
#include "shader_recompiler/runtime_info.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
namespace Vulkan {
PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
AmdGpu::Liverpool* liverpool_)
: instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_}, inst_pool{4096},
block_pool{512} {
const vk::PipelineLayoutCreateInfo layout_info = {
.setLayoutCount = 0U,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
pipeline_layout = instance.GetDevice().createPipelineLayoutUnique(layout_info);
pipeline_cache = instance.GetDevice().createPipelineCacheUnique({});
}
void PipelineCache::BindPipeline() {
SCOPE_EXIT {
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle());
};
if (pipeline) {
return;
}
const auto get_program = [&](const AmdGpu::Liverpool::ShaderProgram& pgm, Shader::Stage stage) {
const u32* token = pgm.Address<u32>();
// Retrieve shader header.
Shader::BinaryInfo bininfo;
std::memcpy(&bininfo, token + (token[1] + 1) * 2, sizeof(bininfo));
// Lookup if the shader already exists.
const auto it = module_map.find(bininfo.shader_hash);
if (it != module_map.end()) {
return *it->second;
}
// Compile and cache shader.
const auto data = std::span{token, bininfo.length / sizeof(u32)};
const auto program = Shader::TranslateProgram(inst_pool, block_pool, stage, data);
return CompileSPV(program, instance.GetDevice());
};
// Retrieve shader stage modules.
// TODO: Only do this when program address is changed.
stages[0] = get_program(liverpool->regs.vs_program, Shader::Stage::Vertex);
stages[4] = get_program(liverpool->regs.ps_program, Shader::Stage::Fragment);
// Bind pipeline.
// TODO: Read entire key based on reg state.
graphics_key.prim_type = liverpool->regs.primitive_type;
graphics_key.polygon_mode = liverpool->regs.polygon_control.PolyMode();
pipeline = std::make_unique<GraphicsPipeline>(instance, graphics_key, *pipeline_cache,
*pipeline_layout, stages);
}
} // namespace Vulkan

View file

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <tsl/robin_map.h>
#include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/object_pool.h"
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
namespace Vulkan {
class Instance;
class Scheduler;
class PipelineCache {
static constexpr size_t MaxShaderStages = 5;
public:
explicit PipelineCache(const Instance& instance, Scheduler& scheduler,
AmdGpu::Liverpool* liverpool);
~PipelineCache() = default;
void BindPipeline();
private:
const Instance& instance;
Scheduler& scheduler;
AmdGpu::Liverpool* liverpool;
vk::UniquePipelineCache pipeline_cache;
vk::UniquePipelineLayout pipeline_layout;
tsl::robin_map<size_t, vk::UniqueShaderModule> module_map;
std::array<vk::ShaderModule, MaxShaderStages> stages{};
std::unique_ptr<GraphicsPipeline> pipeline;
PipelineKey graphics_key{};
Shader::ObjectPool<Shader::IR::Inst> inst_pool;
Shader::ObjectPool<Shader::IR::Block> block_pool;
};
} // namespace Vulkan

View file

@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/texture_cache/image_view.h"
#include "video_core/texture_cache/texture_cache.h"
namespace Vulkan {
static constexpr vk::BufferUsageFlags VertexIndexFlags = vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eTransferDst;
Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
VideoCore::TextureCache& texture_cache_, AmdGpu::Liverpool* liverpool_)
: instance{instance_}, scheduler{scheduler_}, texture_cache{texture_cache_},
liverpool{liverpool_}, pipeline_cache{instance, scheduler, liverpool},
vertex_index_buffer{instance, scheduler, VertexIndexFlags, 64_MB} {
liverpool->BindRasterizer(this);
}
Rasterizer::~Rasterizer() = default;
void Rasterizer::DrawIndex() {
const auto cmdbuf = scheduler.CommandBuffer();
auto& regs = liverpool->regs;
static bool first_time = true;
if (first_time) {
first_time = false;
return;
}
UpdateDynamicState();
pipeline_cache.BindPipeline();
const u32 pitch = regs.color_buffers[0].Pitch();
const u32 height = regs.color_buffers[0].Height();
const u32 tile_max = regs.color_buffers[0].slice.tile_max;
auto& image_view = texture_cache.RenderTarget(regs.color_buffers[0].Address(), pitch);
const vk::RenderingAttachmentInfo color_info = {
.imageView = *image_view.image_view,
.imageLayout = vk::ImageLayout::eGeneral,
.loadOp = vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore,
};
// TODO: Don't restart renderpass every draw
const vk::RenderingInfo rendering_info = {
.renderArea = {.offset = {0, 0}, .extent = {1920, 1080}},
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &color_info,
};
cmdbuf.beginRendering(rendering_info);
cmdbuf.bindIndexBuffer(vertex_index_buffer.Handle(), 0, vk::IndexType::eUint32);
cmdbuf.bindVertexBuffers(0, vertex_index_buffer.Handle(), vk::DeviceSize(0));
cmdbuf.draw(regs.num_indices, regs.num_instances.NumInstances(), 0, 0);
cmdbuf.endRendering();
}
void Rasterizer::UpdateDynamicState() {
UpdateViewportScissorState();
}
void Rasterizer::UpdateViewportScissorState() {
auto& regs = liverpool->regs;
const auto cmdbuf = scheduler.CommandBuffer();
const vk::Viewport viewport{
.x = regs.viewports[0].xoffset - regs.viewports[0].xscale,
.y = regs.viewports[0].yoffset - regs.viewports[0].yscale,
.width = regs.viewports[0].xscale * 2.0f,
.height = regs.viewports[0].yscale * 2.0f,
.minDepth = regs.viewports[0].zoffset - regs.viewports[0].zscale,
.maxDepth = regs.viewports[0].zscale + regs.viewports[0].zoffset,
};
const vk::Rect2D scissor{
.offset = {regs.screen_scissor.top_left_x, regs.screen_scissor.top_left_y},
.extent = {regs.screen_scissor.GetWidth(), regs.screen_scissor.GetHeight()},
};
cmdbuf.setViewport(0, viewport);
cmdbuf.setScissor(0, scissor);
}
void Rasterizer::UpdateDepthStencilState() {
auto& depth = liverpool->regs.depth_control;
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setDepthBoundsTestEnable(depth.depth_bounds_enable);
}
} // namespace Vulkan

View file

@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_stream_buffer.h"
namespace AmdGpu {
struct Liverpool;
}
namespace VideoCore {
class TextureCache;
}
namespace Vulkan {
class Scheduler;
class GraphicsPipeline;
class Rasterizer {
public:
explicit Rasterizer(const Instance& instance, Scheduler& scheduler,
VideoCore::TextureCache& texture_cache, AmdGpu::Liverpool* liverpool);
~Rasterizer();
/// Performs a draw call with an index buffer.
void DrawIndex();
/// Updates graphics state that is not part of the bound pipeline.
void UpdateDynamicState();
private:
/// Updates viewport and scissor from liverpool registers.
void UpdateViewportScissorState();
/// Updates depth and stencil pipeline state from liverpool registers.
void UpdateDepthStencilState();
private:
const Instance& instance;
Scheduler& scheduler;
VideoCore::TextureCache& texture_cache;
AmdGpu::Liverpool* liverpool;
PipelineCache pipeline_cache;
StreamBuffer vertex_index_buffer;
};
} // namespace Vulkan