mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-19 19:14:48 +00:00
renderer_vulkan: Make some primitive state dynamic. (#2764)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / linux-qt-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / linux-qt-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
* 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) {
|
||||
using BlendFactor = Liverpool::BlendControl::BlendFactor;
|
||||
switch (factor) {
|
||||
|
|
|
@ -26,6 +26,8 @@ vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode);
|
|||
|
||||
vk::CullModeFlags CullMode(Liverpool::CullMode mode);
|
||||
|
||||
vk::FrontFace FrontFace(Liverpool::FrontFace mode);
|
||||
|
||||
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
||||
|
||||
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
||||
|
|
|
@ -28,6 +28,15 @@ static constexpr std::array LogicalStageToStageBit = {
|
|||
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(
|
||||
const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
||||
const Shader::Profile& profile, const GraphicsPipelineKey& key_,
|
||||
|
@ -75,19 +84,15 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.pVertexAttributeDescriptions = vertex_attributes.data(),
|
||||
};
|
||||
|
||||
auto prim_restart = key.enable_primitive_restart != 0;
|
||||
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 auto topology = LiverpoolToVK::PrimitiveType(key.prim_type);
|
||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
.topology = LiverpoolToVK::PrimitiveType(key.prim_type),
|
||||
.primitiveRestartEnable = prim_restart,
|
||||
.topology = topology,
|
||||
// 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_quad_list = key.prim_type == AmdGpu::PrimitiveType::QuadList;
|
||||
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
|
||||
|
@ -99,12 +104,6 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.depthClampEnable = false,
|
||||
.rasterizerDiscardEnable = false,
|
||||
.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,
|
||||
};
|
||||
|
||||
|
@ -122,16 +121,20 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.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::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
|
||||
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
|
||||
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
|
||||
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
|
||||
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()) {
|
||||
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
|
||||
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
||||
|
|
|
@ -42,11 +42,7 @@ struct GraphicsPipelineKey {
|
|||
u32 num_samples;
|
||||
u32 mrt_mask;
|
||||
AmdGpu::PrimitiveType prim_type;
|
||||
u32 enable_primitive_restart;
|
||||
u32 primitive_restart_index;
|
||||
Liverpool::PolygonMode polygon_mode;
|
||||
Liverpool::CullMode cull_mode;
|
||||
Liverpool::FrontFace front_face;
|
||||
Liverpool::ClipSpace clip_space;
|
||||
Liverpool::ColorBufferMask cb_shader_mask;
|
||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||
|
@ -82,16 +78,6 @@ public:
|
|||
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.
|
||||
template <typename Attribute, typename Binding>
|
||||
void GetVertexInputs(VertexInputs<Attribute>& attributes, VertexInputs<Binding>& bindings,
|
||||
|
|
|
@ -292,6 +292,11 @@ public:
|
|||
properties.limits.framebufferStencilSampleCounts;
|
||||
}
|
||||
|
||||
/// Returns whether disabling primitive restart is supported.
|
||||
bool IsPrimitiveRestartDisableSupported() const {
|
||||
return driver_id != vk::DriverId::eMoltenvk;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Creates the logical device opportunistically enabling extensions
|
||||
bool CreateDevice();
|
||||
|
|
|
@ -283,12 +283,8 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||
}
|
||||
|
||||
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.cull_mode = regs.polygon_control.CullingMode();
|
||||
key.clip_space = regs.clipper_control.clip_space;
|
||||
key.front_face = regs.polygon_control.front_face;
|
||||
key.num_samples = regs.NumSamples();
|
||||
|
||||
const bool skip_cb_binding =
|
||||
|
|
|
@ -949,6 +949,7 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) {
|
|||
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
||||
UpdateViewportScissorState();
|
||||
UpdateDepthStencilState();
|
||||
UpdatePrimitiveState();
|
||||
|
||||
auto& dynamic_state = scheduler.GetDynamicState();
|
||||
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) {
|
||||
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
|
||||
(!from_guest && !Config::getVkHostMarkersEnabled())) {
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
void UpdateDynamicState(const GraphicsPipeline& pipeline) const;
|
||||
void UpdateViewportScissorState() const;
|
||||
void UpdateDepthStencilState() const;
|
||||
void UpdatePrimitiveState() const;
|
||||
|
||||
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) {
|
||||
dirty_state.blend_constants = false;
|
||||
cmdbuf.setBlendConstants(blend_constants);
|
||||
|
|
|
@ -95,6 +95,10 @@ struct DynamicState {
|
|||
bool stencil_back_write_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 color_write_masks : 1;
|
||||
} dirty_state{};
|
||||
|
@ -125,6 +129,10 @@ struct DynamicState {
|
|||
u32 stencil_back_write_mask{};
|
||||
u32 stencil_back_compare_mask{};
|
||||
|
||||
bool primitive_restart_enable{};
|
||||
vk::CullModeFlags cull_mode{};
|
||||
vk::FrontFace front_face{};
|
||||
|
||||
float blend_constants[4]{};
|
||||
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]) {
|
||||
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
|
||||
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
|
||||
|
|
Loading…
Add table
Reference in a new issue