mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-14 08:12:16 +00:00
renderer_vulkan: Make some primitive state dynamic. (#2764)
* renderer_vulkan: Make some primitive state dynamic. * renderer_vulkan: Silence MoltenVK primitive restart warning spam.
This commit is contained in:
parent
5abec2a291
commit
37d4cd091c
10 changed files with 105 additions and 37 deletions
|
@ -156,6 +156,18 @@ vk::CullModeFlags CullMode(Liverpool::CullMode mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::FrontFace FrontFace(Liverpool::FrontFace face) {
|
||||||
|
switch (face) {
|
||||||
|
case Liverpool::FrontFace::Clockwise:
|
||||||
|
return vk::FrontFace::eClockwise;
|
||||||
|
case Liverpool::FrontFace::CounterClockwise:
|
||||||
|
return vk::FrontFace::eCounterClockwise;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return vk::FrontFace::eClockwise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor) {
|
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor) {
|
||||||
using BlendFactor = Liverpool::BlendControl::BlendFactor;
|
using BlendFactor = Liverpool::BlendControl::BlendFactor;
|
||||||
switch (factor) {
|
switch (factor) {
|
||||||
|
|
|
@ -26,6 +26,8 @@ vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode);
|
||||||
|
|
||||||
vk::CullModeFlags CullMode(Liverpool::CullMode mode);
|
vk::CullModeFlags CullMode(Liverpool::CullMode mode);
|
||||||
|
|
||||||
|
vk::FrontFace FrontFace(Liverpool::FrontFace mode);
|
||||||
|
|
||||||
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
||||||
|
|
||||||
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
||||||
|
|
|
@ -28,6 +28,15 @@ static constexpr std::array LogicalStageToStageBit = {
|
||||||
vk::ShaderStageFlagBits::eCompute,
|
vk::ShaderStageFlagBits::eCompute,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool IsPrimitiveTopologyList(const vk::PrimitiveTopology topology) {
|
||||||
|
return topology == vk::PrimitiveTopology::ePointList ||
|
||||||
|
topology == vk::PrimitiveTopology::eLineList ||
|
||||||
|
topology == vk::PrimitiveTopology::eTriangleList ||
|
||||||
|
topology == vk::PrimitiveTopology::eLineListWithAdjacency ||
|
||||||
|
topology == vk::PrimitiveTopology::eTriangleListWithAdjacency ||
|
||||||
|
topology == vk::PrimitiveTopology::ePatchList;
|
||||||
|
}
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(
|
GraphicsPipeline::GraphicsPipeline(
|
||||||
const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
||||||
const Shader::Profile& profile, const GraphicsPipelineKey& key_,
|
const Shader::Profile& profile, const GraphicsPipelineKey& key_,
|
||||||
|
@ -75,19 +84,15 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
.pVertexAttributeDescriptions = vertex_attributes.data(),
|
.pVertexAttributeDescriptions = vertex_attributes.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prim_restart = key.enable_primitive_restart != 0;
|
const auto topology = LiverpoolToVK::PrimitiveType(key.prim_type);
|
||||||
if (prim_restart && IsPrimitiveListTopology() && !instance.IsListRestartSupported()) {
|
|
||||||
LOG_DEBUG(Render_Vulkan,
|
|
||||||
"Primitive restart is enabled for list topology but not supported by driver.");
|
|
||||||
prim_restart = false;
|
|
||||||
}
|
|
||||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||||
.topology = LiverpoolToVK::PrimitiveType(key.prim_type),
|
.topology = topology,
|
||||||
.primitiveRestartEnable = prim_restart,
|
// Avoid warning spam on all pipelines about unsupported restart disable, if not supported.
|
||||||
|
// However, must be false for list topologies to avoid validation errors.
|
||||||
|
.primitiveRestartEnable =
|
||||||
|
!instance.IsPrimitiveRestartDisableSupported() && !IsPrimitiveTopologyList(topology),
|
||||||
};
|
};
|
||||||
ASSERT_MSG(!prim_restart || key.primitive_restart_index == 0xFFFF ||
|
|
||||||
key.primitive_restart_index == 0xFFFFFFFF,
|
|
||||||
"Primitive restart index other than -1 is not supported yet");
|
|
||||||
const bool is_rect_list = key.prim_type == AmdGpu::PrimitiveType::RectList;
|
const bool is_rect_list = key.prim_type == AmdGpu::PrimitiveType::RectList;
|
||||||
const bool is_quad_list = key.prim_type == AmdGpu::PrimitiveType::QuadList;
|
const bool is_quad_list = key.prim_type == AmdGpu::PrimitiveType::QuadList;
|
||||||
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
|
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
|
||||||
|
@ -99,12 +104,6 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
.depthClampEnable = false,
|
.depthClampEnable = false,
|
||||||
.rasterizerDiscardEnable = false,
|
.rasterizerDiscardEnable = false,
|
||||||
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
|
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
|
||||||
.cullMode = LiverpoolToVK::IsPrimitiveCulled(key.prim_type)
|
|
||||||
? LiverpoolToVK::CullMode(key.cull_mode)
|
|
||||||
: vk::CullModeFlagBits::eNone,
|
|
||||||
.frontFace = key.front_face == Liverpool::FrontFace::Clockwise
|
|
||||||
? vk::FrontFace::eClockwise
|
|
||||||
: vk::FrontFace::eCounterClockwise,
|
|
||||||
.lineWidth = 1.0f,
|
.lineWidth = 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,16 +121,20 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::container::static_vector<vk::DynamicState, 17> dynamic_states = {
|
boost::container::static_vector<vk::DynamicState, 20> dynamic_states = {
|
||||||
vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT,
|
vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT,
|
||||||
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
|
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
|
||||||
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
|
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
|
||||||
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
|
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
|
||||||
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
|
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
|
||||||
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
||||||
vk::DynamicState::eStencilOpEXT,
|
vk::DynamicState::eStencilOpEXT, vk::DynamicState::eCullModeEXT,
|
||||||
|
vk::DynamicState::eFrontFaceEXT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (instance.IsPrimitiveRestartDisableSupported()) {
|
||||||
|
dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnableEXT);
|
||||||
|
}
|
||||||
if (instance.IsDepthBoundsSupported()) {
|
if (instance.IsDepthBoundsSupported()) {
|
||||||
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
|
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
|
||||||
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
||||||
|
|
|
@ -42,11 +42,7 @@ struct GraphicsPipelineKey {
|
||||||
u32 num_samples;
|
u32 num_samples;
|
||||||
u32 mrt_mask;
|
u32 mrt_mask;
|
||||||
AmdGpu::PrimitiveType prim_type;
|
AmdGpu::PrimitiveType prim_type;
|
||||||
u32 enable_primitive_restart;
|
|
||||||
u32 primitive_restart_index;
|
|
||||||
Liverpool::PolygonMode polygon_mode;
|
Liverpool::PolygonMode polygon_mode;
|
||||||
Liverpool::CullMode cull_mode;
|
|
||||||
Liverpool::FrontFace front_face;
|
|
||||||
Liverpool::ClipSpace clip_space;
|
Liverpool::ClipSpace clip_space;
|
||||||
Liverpool::ColorBufferMask cb_shader_mask;
|
Liverpool::ColorBufferMask cb_shader_mask;
|
||||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||||
|
@ -82,16 +78,6 @@ public:
|
||||||
return key.mrt_mask;
|
return key.mrt_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsPrimitiveListTopology() const {
|
|
||||||
return key.prim_type == AmdGpu::PrimitiveType::PointList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::LineList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::TriangleList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::AdjLineList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::AdjTriangleList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::RectList ||
|
|
||||||
key.prim_type == AmdGpu::PrimitiveType::QuadList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the attributes and bindings for vertex inputs.
|
/// Gets the attributes and bindings for vertex inputs.
|
||||||
template <typename Attribute, typename Binding>
|
template <typename Attribute, typename Binding>
|
||||||
void GetVertexInputs(VertexInputs<Attribute>& attributes, VertexInputs<Binding>& bindings,
|
void GetVertexInputs(VertexInputs<Attribute>& attributes, VertexInputs<Binding>& bindings,
|
||||||
|
|
|
@ -292,6 +292,11 @@ public:
|
||||||
properties.limits.framebufferStencilSampleCounts;
|
properties.limits.framebufferStencilSampleCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether disabling primitive restart is supported.
|
||||||
|
bool IsPrimitiveRestartDisableSupported() const {
|
||||||
|
return driver_id != vk::DriverId::eMoltenvk;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Creates the logical device opportunistically enabling extensions
|
/// Creates the logical device opportunistically enabling extensions
|
||||||
bool CreateDevice();
|
bool CreateDevice();
|
||||||
|
|
|
@ -283,12 +283,8 @@ bool PipelineCache::RefreshGraphicsKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
key.prim_type = regs.primitive_type;
|
key.prim_type = regs.primitive_type;
|
||||||
key.enable_primitive_restart = regs.enable_primitive_restart & 1;
|
|
||||||
key.primitive_restart_index = regs.primitive_restart_index;
|
|
||||||
key.polygon_mode = regs.polygon_control.PolyMode();
|
key.polygon_mode = regs.polygon_control.PolyMode();
|
||||||
key.cull_mode = regs.polygon_control.CullingMode();
|
|
||||||
key.clip_space = regs.clipper_control.clip_space;
|
key.clip_space = regs.clipper_control.clip_space;
|
||||||
key.front_face = regs.polygon_control.front_face;
|
|
||||||
key.num_samples = regs.NumSamples();
|
key.num_samples = regs.NumSamples();
|
||||||
|
|
||||||
const bool skip_cb_binding =
|
const bool skip_cb_binding =
|
||||||
|
|
|
@ -949,6 +949,7 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) {
|
||||||
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
||||||
UpdateViewportScissorState();
|
UpdateViewportScissorState();
|
||||||
UpdateDepthStencilState();
|
UpdateDepthStencilState();
|
||||||
|
UpdatePrimitiveState();
|
||||||
|
|
||||||
auto& dynamic_state = scheduler.GetDynamicState();
|
auto& dynamic_state = scheduler.GetDynamicState();
|
||||||
dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red);
|
dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red);
|
||||||
|
@ -1132,6 +1133,25 @@ void Rasterizer::UpdateDepthStencilState() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rasterizer::UpdatePrimitiveState() const {
|
||||||
|
const auto& regs = liverpool->regs;
|
||||||
|
auto& dynamic_state = scheduler.GetDynamicState();
|
||||||
|
|
||||||
|
const auto prim_restart = (regs.enable_primitive_restart & 1) != 0;
|
||||||
|
ASSERT_MSG(!prim_restart || regs.primitive_restart_index == 0xFFFF ||
|
||||||
|
regs.primitive_restart_index == 0xFFFFFFFF,
|
||||||
|
"Primitive restart index other than -1 is not supported yet");
|
||||||
|
|
||||||
|
const auto cull_mode = LiverpoolToVK::IsPrimitiveCulled(regs.primitive_type)
|
||||||
|
? LiverpoolToVK::CullMode(regs.polygon_control.CullingMode())
|
||||||
|
: vk::CullModeFlagBits::eNone;
|
||||||
|
const auto front_face = LiverpoolToVK::FrontFace(regs.polygon_control.front_face);
|
||||||
|
|
||||||
|
dynamic_state.SetPrimitiveRestartEnabled(prim_restart);
|
||||||
|
dynamic_state.SetCullMode(cull_mode);
|
||||||
|
dynamic_state.SetFrontFace(front_face);
|
||||||
|
}
|
||||||
|
|
||||||
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
|
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
|
||||||
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
|
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
|
||||||
(!from_guest && !Config::getVkHostMarkersEnabled())) {
|
(!from_guest && !Config::getVkHostMarkersEnabled())) {
|
||||||
|
|
|
@ -78,6 +78,7 @@ private:
|
||||||
void UpdateDynamicState(const GraphicsPipeline& pipeline) const;
|
void UpdateDynamicState(const GraphicsPipeline& pipeline) const;
|
||||||
void UpdateViewportScissorState() const;
|
void UpdateViewportScissorState() const;
|
||||||
void UpdateDepthStencilState() const;
|
void UpdateDepthStencilState() const;
|
||||||
|
void UpdatePrimitiveState() const;
|
||||||
|
|
||||||
bool FilterDraw();
|
bool FilterDraw();
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,20 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dirty_state.primitive_restart_enable) {
|
||||||
|
dirty_state.primitive_restart_enable = false;
|
||||||
|
if (instance.IsPrimitiveRestartDisableSupported()) {
|
||||||
|
cmdbuf.setPrimitiveRestartEnableEXT(primitive_restart_enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirty_state.cull_mode) {
|
||||||
|
dirty_state.cull_mode = false;
|
||||||
|
cmdbuf.setCullModeEXT(cull_mode);
|
||||||
|
}
|
||||||
|
if (dirty_state.front_face) {
|
||||||
|
dirty_state.front_face = false;
|
||||||
|
cmdbuf.setFrontFaceEXT(front_face);
|
||||||
|
}
|
||||||
if (dirty_state.blend_constants) {
|
if (dirty_state.blend_constants) {
|
||||||
dirty_state.blend_constants = false;
|
dirty_state.blend_constants = false;
|
||||||
cmdbuf.setBlendConstants(blend_constants);
|
cmdbuf.setBlendConstants(blend_constants);
|
||||||
|
|
|
@ -95,6 +95,10 @@ struct DynamicState {
|
||||||
bool stencil_back_write_mask : 1;
|
bool stencil_back_write_mask : 1;
|
||||||
bool stencil_back_compare_mask : 1;
|
bool stencil_back_compare_mask : 1;
|
||||||
|
|
||||||
|
bool primitive_restart_enable : 1;
|
||||||
|
bool cull_mode : 1;
|
||||||
|
bool front_face : 1;
|
||||||
|
|
||||||
bool blend_constants : 1;
|
bool blend_constants : 1;
|
||||||
bool color_write_masks : 1;
|
bool color_write_masks : 1;
|
||||||
} dirty_state{};
|
} dirty_state{};
|
||||||
|
@ -125,6 +129,10 @@ struct DynamicState {
|
||||||
u32 stencil_back_write_mask{};
|
u32 stencil_back_write_mask{};
|
||||||
u32 stencil_back_compare_mask{};
|
u32 stencil_back_compare_mask{};
|
||||||
|
|
||||||
|
bool primitive_restart_enable{};
|
||||||
|
vk::CullModeFlags cull_mode{};
|
||||||
|
vk::FrontFace front_face{};
|
||||||
|
|
||||||
float blend_constants[4]{};
|
float blend_constants[4]{};
|
||||||
ColorWriteMasks color_write_masks{};
|
ColorWriteMasks color_write_masks{};
|
||||||
|
|
||||||
|
@ -254,6 +262,27 @@ struct DynamicState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPrimitiveRestartEnabled(const bool enabled) {
|
||||||
|
if (primitive_restart_enable != enabled) {
|
||||||
|
primitive_restart_enable = enabled;
|
||||||
|
dirty_state.primitive_restart_enable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCullMode(const vk::CullModeFlags cull_mode_) {
|
||||||
|
if (cull_mode != cull_mode_) {
|
||||||
|
cull_mode = cull_mode_;
|
||||||
|
dirty_state.cull_mode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFrontFace(const vk::FrontFace front_face_) {
|
||||||
|
if (front_face != front_face_) {
|
||||||
|
front_face = front_face_;
|
||||||
|
dirty_state.front_face = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetBlendConstants(const float blend_constants_[4]) {
|
void SetBlendConstants(const float blend_constants_[4]) {
|
||||||
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
|
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
|
||||||
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
|
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
|
||||||
|
|
Loading…
Add table
Reference in a new issue