Browse Source

[vulkan] Adding VK_EXT_color_write_enable

qcomopts2
CamilleLaVey 7 days ago
parent
commit
6e73a5e395
  1. 50
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  2. 27
      src/video_core/vulkan_common/vulkan_device.cpp
  3. 6
      src/video_core/vulkan_common/vulkan_device.h
  4. 3
      src/video_core/vulkan_common/vulkan_wrapper.cpp
  5. 7
      src/video_core/vulkan_common/vulkan_wrapper.h

50
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -1070,6 +1070,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
}
// EDS3 Blending: ColorBlendEnable, ColorBlendEquation, ColorWriteMask
// or VK_EXT_color_write_enable if EDS3 is not available
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
UpdateBlending(regs);
}
@ -1673,26 +1674,41 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) {
}
if (state_tracker.TouchColorMask()) {
std::array<VkColorComponentFlags, Maxwell::NumRenderTargets> setup_masks{};
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) {
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
auto& current = setup_masks[index];
if (mask.R) {
current |= VK_COLOR_COMPONENT_R_BIT;
}
if (mask.G) {
current |= VK_COLOR_COMPONENT_G_BIT;
}
if (mask.B) {
current |= VK_COLOR_COMPONENT_B_BIT;
// Use VK_EXT_color_write_enable if available and EDS3 is not active
if (device.IsExtColorWriteEnableSupported()) {
// With color_write_enable, we set enable/disable per attachment
std::array<VkBool32, Maxwell::NumRenderTargets> setup_enables{};
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) {
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
// Enable writing only if at least one component is enabled
setup_enables[index] = (mask.R || mask.G || mask.B || mask.A) ? VK_TRUE : VK_FALSE;
}
if (mask.A) {
current |= VK_COLOR_COMPONENT_A_BIT;
scheduler.Record([setup_enables](vk::CommandBuffer cmdbuf) {
cmdbuf.SetColorWriteEnableEXT(0, setup_enables);
});
} else {
// Fallback: Use ColorWriteMask from EDS3
std::array<VkColorComponentFlags, Maxwell::NumRenderTargets> setup_masks{};
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) {
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
auto& current = setup_masks[index];
if (mask.R) {
current |= VK_COLOR_COMPONENT_R_BIT;
}
if (mask.G) {
current |= VK_COLOR_COMPONENT_G_BIT;
}
if (mask.B) {
current |= VK_COLOR_COMPONENT_B_BIT;
}
if (mask.A) {
current |= VK_COLOR_COMPONENT_A_BIT;
}
}
scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) {
cmdbuf.SetColorWriteMaskEXT(0, setup_masks);
});
}
scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) {
cmdbuf.SetColorWriteMaskEXT(0, setup_masks);
});
}
if (state_tracker.TouchBlendEnable()) {

27
src/video_core/vulkan_common/vulkan_device.cpp

@ -1394,8 +1394,19 @@ void Device::RemoveUnsuitableExtensions() {
features.extended_dynamic_state3,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
// VK_EXT_color_write_enable
if (extensions.extended_dynamic_state3 && dynamic_state3_blending) {
LOG_INFO(Render_Vulkan, "VK_EXT_color_write_enable disabled: VK_EXT_extended_dynamic_state3 provides ColorWriteMask functionality");
RemoveExtensionFeature(extensions.color_write_enable, features.color_write_enable,
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
} else {
extensions.color_write_enable = features.color_write_enable.colorWriteEnable;
RemoveExtensionFeatureIfUnsuitable(extensions.color_write_enable,
features.color_write_enable,
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
}
// VK_EXT_robustness2
// Enable if at least one robustness2 feature is available
extensions.robustness_2 = features.robustness2.robustBufferAccess2 ||
features.robustness2.robustImageAccess2 ||
features.robustness2.nullDescriptor;
@ -1404,7 +1415,6 @@ void Device::RemoveUnsuitableExtensions() {
VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
// VK_EXT_image_robustness
// Enable if robustImageAccess is available
extensions.image_robustness = features.image_robustness.robustImageAccess;
RemoveExtensionFeatureIfUnsuitable(extensions.image_robustness, features.image_robustness,
VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME);
@ -1505,7 +1515,6 @@ void Device::RemoveUnsuitableExtensions() {
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
// VK_EXT_swapchain_maintenance1 (extension only, has features)
// Requires VK_EXT_surface_maintenance1 instance extension
extensions.swapchain_maintenance1 = features.swapchain_maintenance1.swapchainMaintenance1;
if (extensions.swapchain_maintenance1) {
// Check if VK_EXT_surface_maintenance1 instance extension is available
@ -1524,15 +1533,15 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.swapchain_maintenance1, features.swapchain_maintenance1,
VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
// VK_KHR_maintenance1 (core in Vulkan 1.1, no features)
// VK_KHR_maintenance1
extensions.maintenance1 = loaded_extensions.contains(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance1, VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
// VK_KHR_maintenance2 (core in Vulkan 1.1, no features)
// VK_KHR_maintenance2
extensions.maintenance2 = loaded_extensions.contains(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance2, VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
// VK_KHR_maintenance3 (core in Vulkan 1.1, no features)
// VK_KHR_maintenance3
extensions.maintenance3 = loaded_extensions.contains(VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance3, VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
@ -1562,15 +1571,15 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.maintenance6, features.maintenance6,
VK_KHR_MAINTENANCE_6_EXTENSION_NAME);
// VK_KHR_maintenance7 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance7
extensions.maintenance7 = loaded_extensions.contains(VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance7, VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
// VK_KHR_maintenance8 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance8
extensions.maintenance8 = loaded_extensions.contains(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance8, VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
// VK_KHR_maintenance9 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance9
extensions.maintenance9 = loaded_extensions.contains(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance9, VK_KHR_MAINTENANCE_9_EXTENSION_NAME);

6
src/video_core/vulkan_common/vulkan_device.h

@ -48,6 +48,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
// Define all features which may be used by the implementation and require an extension here.
#define FOR_EACH_VK_FEATURE_EXT(FEATURE) \
FEATURE(EXT, ColorWriteEnable, COLOR_WRITE_ENABLE, color_write_enable) \
FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \
FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \
FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \
@ -571,6 +572,11 @@ public:
return extensions.custom_border_color;
}
/// Returns true if the device supports VK_EXT_color_write_enable.
bool IsExtColorWriteEnableSupported() const {
return extensions.color_write_enable;
}
/// Returns true if the device supports VK_EXT_image_robustness.
bool IsExtImageRobustnessSupported() const {
return extensions.image_robustness;

3
src/video_core/vulkan_common/vulkan_wrapper.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -165,6 +165,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetColorWriteMaskEXT);
X(vkCmdSetColorBlendEnableEXT);
X(vkCmdSetColorBlendEquationEXT);
X(vkCmdSetColorWriteEnableEXT);
X(vkCmdResolveImage);
X(vkCreateBuffer);
X(vkCreateBufferView);

7
src/video_core/vulkan_common/vulkan_wrapper.h

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -265,6 +265,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{};
PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT{};
PFN_vkCmdWaitEvents vkCmdWaitEvents{};
PFN_vkCreateBuffer vkCreateBuffer{};
PFN_vkCreateBufferView vkCreateBufferView{};
@ -1521,6 +1522,10 @@ public:
dld->vkCmdSetColorBlendEquationEXT(handle, first, equations.size(), equations.data());
}
void SetColorWriteEnableEXT(u32 first, Span<VkBool32> enables) const noexcept {
dld->vkCmdSetColorWriteEnableEXT(handle, first, enables.size(), enables.data());
}
void SetLineWidth(float line_width) const noexcept {
dld->vkCmdSetLineWidth(handle, line_width);
}

Loading…
Cancel
Save