video_core: renderer_vulkan: write mask fallback

This commit is contained in:
psucien 2024-05-30 16:27:39 +02:00
parent 8e6d492524
commit 365df2a3ac
7 changed files with 43 additions and 21 deletions

View File

@ -416,6 +416,10 @@ struct Liverpool {
BitField<20, 4, u32> output5_mask; BitField<20, 4, u32> output5_mask;
BitField<24, 4, u32> output6_mask; BitField<24, 4, u32> output6_mask;
BitField<28, 4, u32> output7_mask; BitField<28, 4, u32> output7_mask;
[[nodiscard]] u8 GetMask(int buf_id) const {
return (raw >> (buf_id * 4)) & 0xffu;
}
}; };
struct IndexBufferBase { struct IndexBufferBase {

View File

@ -185,8 +185,11 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
.srcAlphaBlendFactor = LiverpoolToVK::BlendFactor(control.alpha_src_factor), .srcAlphaBlendFactor = LiverpoolToVK::BlendFactor(control.alpha_src_factor),
.dstAlphaBlendFactor = LiverpoolToVK::BlendFactor(control.color_dst_factor), .dstAlphaBlendFactor = LiverpoolToVK::BlendFactor(control.color_dst_factor),
.alphaBlendOp = LiverpoolToVK::BlendOp(control.alpha_func), .alphaBlendOp = LiverpoolToVK::BlendOp(control.alpha_func),
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | .colorWriteMask =
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, instance.IsColorWriteEnableSupported()
? vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA
: key.write_masks[i],
}; };
} }

View File

@ -39,6 +39,7 @@ struct GraphicsPipelineKey {
Liverpool::PolygonMode polygon_mode; Liverpool::PolygonMode polygon_mode;
Liverpool::CullMode cull_mode; Liverpool::CullMode cull_mode;
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls; std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
bool operator==(const GraphicsPipelineKey& key) const noexcept { bool operator==(const GraphicsPipelineKey& key) const noexcept {
return std::memcmp(this, &key, sizeof(GraphicsPipelineKey)) == 0; return std::memcmp(this, &key, sizeof(GraphicsPipelineKey)) == 0;
@ -66,6 +67,10 @@ public:
return key.stage_hashes[0] == EmbeddedVsHash; return key.stage_hashes[0] == EmbeddedVsHash;
} }
[[nodiscard]] auto GetWriteMasks() const {
return key.write_masks;
}
private: private:
void BuildDescSetLayout(); void BuildDescSetLayout();

View File

@ -151,10 +151,11 @@ bool Instance::CreateDevice() {
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
index_type_uint8 = add_extension(VK_KHR_INDEX_TYPE_UINT8_EXTENSION_NAME); index_type_uint8 = add_extension(VK_KHR_INDEX_TYPE_UINT8_EXTENSION_NAME);
color_write_en = add_extension(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
// The next two extensions are required to be available together in order to support write masks
color_write_en = add_extension(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
color_write_en &= add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
const auto family_properties = physical_device.getQueueFamilyProperties(); const auto family_properties = physical_device.getQueueFamilyProperties();
if (family_properties.empty()) { if (family_properties.empty()) {
@ -194,6 +195,7 @@ bool Instance::CreateDevice() {
vk::PhysicalDeviceFeatures2{ vk::PhysicalDeviceFeatures2{
.features{ .features{
.robustBufferAccess = features.robustBufferAccess, .robustBufferAccess = features.robustBufferAccess,
.independentBlend = true,
.geometryShader = features.geometryShader, .geometryShader = features.geometryShader,
.logicOp = features.logicOp, .logicOp = features.logicOp,
.samplerAnisotropy = features.samplerAnisotropy, .samplerAnisotropy = features.samplerAnisotropy,
@ -233,6 +235,7 @@ bool Instance::CreateDevice() {
if (!color_write_en) { if (!color_write_en) {
device_chain.unlink<vk::PhysicalDeviceColorWriteEnableFeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceColorWriteEnableFeaturesEXT>();
device_chain.unlink<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
} }
try { try {

View File

@ -93,16 +93,26 @@ void PipelineCache::RefreshGraphicsKey() {
key.stencil_ref_back = regs.stencil_ref_back; key.stencil_ref_back = regs.stencil_ref_back;
key.prim_type = regs.primitive_type; key.prim_type = regs.primitive_type;
key.polygon_mode = regs.polygon_control.PolyMode(); key.polygon_mode = regs.polygon_control.PolyMode();
key.blend_controls = regs.blend_control;
const auto& db = regs.depth_buffer; const auto& db = regs.depth_buffer;
key.depth_format = key.depth.depth_enable key.depth_format = key.depth.depth_enable
? LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format) ? LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format)
: vk::Format::eUndefined; : vk::Format::eUndefined;
for (u32 i = 0; i < Liverpool::NumColorBuffers; i++) { // `RenderingInfo` is assumed to be initialized with a contiguous array of valid color
const auto& cb = regs.color_buffers[i]; // attachments. This might be not a case as HW color buffers can be bound in an arbitrary order.
key.color_formats[i] = cb ? LiverpoolToVK::SurfaceFormat(cb.info.format, cb.NumFormat()) // We need to do some arrays compaction at this stage
: vk::Format::eUndefined; int remapped_cb{};
for (auto cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) {
auto const& col_buf = regs.color_buffers[cb];
if (!col_buf) {
continue;
}
key.color_formats[remapped_cb] =
LiverpoolToVK::SurfaceFormat(col_buf.info.format, col_buf.NumFormat());
key.blend_controls[remapped_cb] = regs.blend_control[cb];
key.write_masks[remapped_cb] = vk::ColorComponentFlags{regs.color_target_mask.GetMask(cb)};
++remapped_cb;
} }
for (u32 i = 0; i < MaxShaderStages; i++) { for (u32 i = 0; i < MaxShaderStages; i++) {

View File

@ -68,7 +68,7 @@ void Rasterizer::Draw(bool is_indexed) {
.pColorAttachments = color_attachments.data(), .pColorAttachments = color_attachments.data(),
}; };
UpdateDynamicState(); UpdateDynamicState(*pipeline);
cmdbuf.beginRendering(rendering_info); cmdbuf.beginRendering(rendering_info);
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle()); cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle());
@ -132,7 +132,7 @@ u32 Rasterizer::SetupIndexBuffer(bool& is_indexed) {
return regs.num_indices; return regs.num_indices;
} }
void Rasterizer::UpdateDynamicState() { void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
UpdateViewportScissorState(); UpdateViewportScissorState();
auto& regs = liverpool->regs; auto& regs = liverpool->regs;
@ -140,16 +140,13 @@ void Rasterizer::UpdateDynamicState() {
cmdbuf.setBlendConstants(&regs.blend_constants.red); cmdbuf.setBlendConstants(&regs.blend_constants.red);
if (instance.IsColorWriteEnableSupported()) { if (instance.IsColorWriteEnableSupported()) {
std::array<VkBool32, Liverpool::NumColorBuffers> write_en{}; const auto& write_masks = pipeline.GetWriteMasks();
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_mask{}; std::array<vk::Bool32, Liverpool::NumColorBuffers> write_ens{};
for (int col_buf_idx = 0; col_buf_idx < Liverpool::NumColorBuffers; ++col_buf_idx) { std::transform(write_masks.cbegin(), write_masks.cend(), write_ens.begin(),
const auto mask = regs.color_target_mask.raw >> (col_buf_idx * 4); [](auto in) { return in ? vk::True : vk::False; });
write_en[col_buf_idx] = mask ? vk::True : vk::False;
write_mask[col_buf_idx] = vk::ColorComponentFlags{mask};
}
cmdbuf.setColorWriteEnableEXT(write_en); cmdbuf.setColorWriteEnableEXT(write_ens);
cmdbuf.setColorWriteMaskEXT(0, write_mask); cmdbuf.setColorWriteMaskEXT(0, write_masks);
} }
} }

View File

@ -37,7 +37,7 @@ private:
u32 SetupIndexBuffer(bool& is_indexed); u32 SetupIndexBuffer(bool& is_indexed);
void MapMemory(VAddr addr, size_t size); void MapMemory(VAddr addr, size_t size);
void UpdateDynamicState(); void UpdateDynamicState(const GraphicsPipeline& pipeline);
void UpdateViewportScissorState(); void UpdateViewportScissorState();
void UpdateDepthStencilState(); void UpdateDepthStencilState();