Browse Source

[vulkan] Implementation color write enable + color border swizzle

lsfg-android
CamilleLaVey 4 weeks ago
parent
commit
fbd94e4237
  1. 10
      src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
  2. 2
      src/video_core/renderer_vulkan/fixed_pipeline_state.h
  3. 11
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  4. 7
      src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
  5. 17
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  6. 1
      src/video_core/renderer_vulkan/vk_rasterizer.h
  7. 5
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  8. 15
      src/video_core/vulkan_common/vulkan_device.cpp
  9. 17
      src/video_core/vulkan_common/vulkan_device.h
  10. 1
      src/video_core/vulkan_common/vulkan_wrapper.cpp
  11. 5
      src/video_core/vulkan_common/vulkan_wrapper.h

10
src/video_core/renderer_vulkan/fixed_pipeline_state.cpp

@ -80,6 +80,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
extended_dynamic_state_2_logic_op.Assign(features.has_extended_dynamic_state_2_logic_op ? 1 : 0); extended_dynamic_state_2_logic_op.Assign(features.has_extended_dynamic_state_2_logic_op ? 1 : 0);
extended_dynamic_state_3_blend.Assign(features.has_extended_dynamic_state_3_blend ? 1 : 0); extended_dynamic_state_3_blend.Assign(features.has_extended_dynamic_state_3_blend ? 1 : 0);
extended_dynamic_state_3_enables.Assign(features.has_extended_dynamic_state_3_enables ? 1 : 0); extended_dynamic_state_3_enables.Assign(features.has_extended_dynamic_state_3_enables ? 1 : 0);
color_write_enable_dynamic.Assign(features.has_color_write_enable ? 1 : 0);
dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0); dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0);
xfb_enabled.Assign(regs.transform_feedback_enabled != 0); xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0); ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
@ -209,6 +210,15 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
maxwell3d.dirty.flags[Dirty::Blending] = false; maxwell3d.dirty.flags[Dirty::Blending] = false;
for (size_t index = 0; index < attachments.size(); ++index) { for (size_t index = 0; index < attachments.size(); ++index) {
attachments[index].Refresh(regs, index); attachments[index].Refresh(regs, index);
auto& attachment = attachments[index];
if (color_write_enable_dynamic && attachment.mask_r == 0 &&
attachment.mask_g == 0 && attachment.mask_b == 0 &&
attachment.mask_a == 0) {
attachment.mask_r.Assign(1);
attachment.mask_g.Assign(1);
attachment.mask_b.Assign(1);
attachment.mask_a.Assign(1);
}
} }
} }
} }

2
src/video_core/renderer_vulkan/fixed_pipeline_state.h

@ -31,6 +31,7 @@ struct DynamicFeatures {
bool has_dynamic_state3_logic_op_enable; bool has_dynamic_state3_logic_op_enable;
bool has_dynamic_state3_line_stipple_enable; bool has_dynamic_state3_line_stipple_enable;
bool has_dynamic_vertex_input; bool has_dynamic_vertex_input;
bool has_color_write_enable;
bool has_provoking_vertex; bool has_provoking_vertex;
bool has_provoking_vertex_first_mode; bool has_provoking_vertex_first_mode;
bool has_provoking_vertex_last_mode; bool has_provoking_vertex_last_mode;
@ -208,6 +209,7 @@ struct FixedPipelineState {
BitField<12, 2, u32> tessellation_spacing; BitField<12, 2, u32> tessellation_spacing;
BitField<14, 1, u32> tessellation_clockwise; BitField<14, 1, u32> tessellation_clockwise;
BitField<15, 5, u32> patch_control_points_minus_one; BitField<15, 5, u32> patch_control_points_minus_one;
BitField<20, 1, u32> color_write_enable_dynamic;
BitField<24, 4, Maxwell::PrimitiveTopology> topology; BitField<24, 4, Maxwell::PrimitiveTopology> topology;
BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode; BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode;

11
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -869,15 +869,13 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
}; };
dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
// VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT is part of EDS1
// Only use it if VIDS is not active (VIDS replaces it with full vertex input control)
// VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT
if (!key.state.dynamic_vertex_input) { if (!key.state.dynamic_vertex_input) {
dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT); dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
} }
} }
// VK_DYNAMIC_STATE_VERTEX_INPUT_EXT (VIDS) - Independent from EDS
// Provides full dynamic vertex input control, replaces VERTEX_INPUT_BINDING_STRIDE
// VK_DYNAMIC_STATE_VERTEX_INPUT_EXT
if (key.state.dynamic_vertex_input) { if (key.state.dynamic_vertex_input) {
dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT); dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
} }
@ -907,6 +905,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
dynamic_states.insert(dynamic_states.end(), extended3.begin(), extended3.end()); dynamic_states.insert(dynamic_states.end(), extended3.begin(), extended3.end());
} }
// VK_EXT_color_write_enable fallback for fully on/off render targets when EDS3 blending is not available.
if (!key.state.extended_dynamic_state_3_blend && key.state.color_write_enable_dynamic) {
dynamic_states.push_back(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
}
// EDS3 - Enables (composite: per-feature) // EDS3 - Enables (composite: per-feature)
if (key.state.extended_dynamic_state_3_enables) { if (key.state.extended_dynamic_state_3_enables) {
if (device.SupportsDynamicState3DepthClampEnable()) { if (device.SupportsDynamicState3DepthClampEnable()) {

7
src/video_core/renderer_vulkan/vk_pipeline_cache.cpp

@ -500,6 +500,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
device.IsExtExtendedDynamicState3BlendingSupported(); device.IsExtExtendedDynamicState3BlendingSupported();
dynamic_features.has_extended_dynamic_state_3_enables = dynamic_features.has_extended_dynamic_state_3_enables =
device.IsExtExtendedDynamicState3EnablesSupported(); device.IsExtExtendedDynamicState3EnablesSupported();
dynamic_features.has_color_write_enable =
device.IsExtColorWriteEnableSupported();
dynamic_features.has_dynamic_state3_depth_clamp_enable = dynamic_features.has_dynamic_state3_depth_clamp_enable =
dynamic_features.has_extended_dynamic_state_3_enables && dynamic_features.has_extended_dynamic_state_3_enables &&
device.SupportsDynamicState3DepthClampEnable(); device.SupportsDynamicState3DepthClampEnable();
@ -632,7 +634,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
dynamic_features.has_extended_dynamic_state_3_blend || dynamic_features.has_extended_dynamic_state_3_blend ||
(key.state.extended_dynamic_state_3_enables != 0) != (key.state.extended_dynamic_state_3_enables != 0) !=
dynamic_features.has_extended_dynamic_state_3_enables || dynamic_features.has_extended_dynamic_state_3_enables ||
(key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
(key.state.color_write_enable_dynamic != 0) !=
dynamic_features.has_color_write_enable ||
(key.state.dynamic_vertex_input != 0) !=
dynamic_features.has_dynamic_vertex_input) {
return; return;
} }

17
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -1080,6 +1080,8 @@ void RasterizerVulkan::UpdateDynamicStates() {
if (device.IsExtExtendedDynamicState3BlendingSupported()) { if (device.IsExtExtendedDynamicState3BlendingSupported()) {
UpdateBlending(regs); UpdateBlending(regs);
} else if (device.IsExtColorWriteEnableSupported()) {
UpdateColorWriteEnable(regs);
} }
if (device.IsExtVertexInputDynamicStateSupported()) { if (device.IsExtVertexInputDynamicStateSupported()) {
@ -1094,7 +1096,6 @@ void RasterizerVulkan::HandleTransformFeedback() {
const auto& regs = maxwell3d->regs; const auto& regs = maxwell3d->regs;
if (!device.IsExtTransformFeedbackSupported()) { if (!device.IsExtTransformFeedbackSupported()) {
// If the guest enabled transform feedback, warn once that the device lacks support.
if (regs.transform_feedback_enabled != 0) { if (regs.transform_feedback_enabled != 0) {
std::call_once(warn_unsupported, [&] { std::call_once(warn_unsupported, [&] {
LOG_WARNING(Render_Vulkan, "Transform feedback requested by guest but VK_EXT_transform_feedback is unavailable; queries disabled"); LOG_WARNING(Render_Vulkan, "Transform feedback requested by guest but VK_EXT_transform_feedback is unavailable; queries disabled");
@ -1774,6 +1775,20 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) {
} }
} }
void RasterizerVulkan::UpdateColorWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchColorMask()) {
return;
}
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];
setup_enables[index] = (mask.R || mask.G || mask.B || mask.A) ? VK_TRUE : VK_FALSE;
}
scheduler.Record([setup_enables](vk::CommandBuffer cmdbuf) {
cmdbuf.SetColorWriteEnableEXT(0, setup_enables);
});
}
void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) { void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchStencilTestEnable()) { if (!state_tracker.TouchStencilTestEnable()) {
return; return;

1
src/video_core/renderer_vulkan/vk_rasterizer.h

@ -191,6 +191,7 @@ private:
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateColorWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);

5
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -2297,12 +2297,15 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
const void* pnext = nullptr; const void* pnext = nullptr;
if (has_custom_border_colors) { if (has_custom_border_colors) {
pnext = &border_ci; pnext = &border_ci;
// Log extension usage for custom border color
if (GPU::Logging::IsActive()) { if (GPU::Logging::IsActive()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage( GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
"VK_EXT_custom_border_color", "Sampler::Sampler"); "VK_EXT_custom_border_color", "Sampler::Sampler");
} }
} }
if (device.IsExtBorderColorSwizzleSupported() && GPU::Logging::IsActive()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
"VK_EXT_border_color_swizzle", "Sampler::Sampler");
}
const VkSamplerReductionModeCreateInfoEXT reduction_ci{ const VkSamplerReductionModeCreateInfoEXT reduction_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,
.pNext = pnext, .pNext = pnext,

15
src/video_core/vulkan_common/vulkan_device.cpp

@ -1170,6 +1170,21 @@ bool Device::GetSuitability(bool requires_swapchain) {
} }
void Device::RemoveUnsuitableExtensions() { void Device::RemoveUnsuitableExtensions() {
// VK_EXT_color_write_enable
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_border_color_swizzle
if (extensions.border_color_swizzle) {
extensions.border_color_swizzle =
features.border_color_swizzle.borderColorSwizzle &&
features.border_color_swizzle.borderColorSwizzleFromImage;
}
RemoveExtensionFeatureIfUnsuitable(extensions.border_color_swizzle,
features.border_color_swizzle,
VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME);
// VK_EXT_custom_border_color // VK_EXT_custom_border_color
if (extensions.custom_border_color) { if (extensions.custom_border_color) {
extensions.custom_border_color = extensions.custom_border_color =

17
src/video_core/vulkan_common/vulkan_device.h

@ -50,6 +50,8 @@ VK_DEFINE_HANDLE(VmaAllocator)
// Define all features which may be used by the implementation and require an extension here. // Define all features which may be used by the implementation and require an extension here.
#define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \
FEATURE(EXT, BorderColorSwizzle, BORDER_COLOR_SWIZZLE, border_color_swizzle) \
FEATURE(EXT, ColorWriteEnable, COLOR_WRITE_ENABLE, color_write_enable) \
FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \ FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \
FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \ FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \
FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \
@ -584,6 +586,21 @@ FN_MAX_LIMIT_LIST
return features.custom_border_color.customBorderColorWithoutFormat; return features.custom_border_color.customBorderColorWithoutFormat;
} }
/// 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_border_color_swizzle.
bool IsExtBorderColorSwizzleSupported() const {
return extensions.border_color_swizzle;
}
/// Returns true if borderColorSwizzleFromImage is available.
bool IsBorderColorSwizzleFromImageSupported() const {
return features.border_color_swizzle.borderColorSwizzleFromImage;
}
/// Returns true if the device supports VK_EXT_extended_dynamic_state. /// Returns true if the device supports VK_EXT_extended_dynamic_state.
bool IsExtExtendedDynamicStateSupported() const { bool IsExtExtendedDynamicStateSupported() const {
return extensions.extended_dynamic_state; return extensions.extended_dynamic_state;

1
src/video_core/vulkan_common/vulkan_wrapper.cpp

@ -162,6 +162,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetStencilTestEnableEXT); X(vkCmdSetStencilTestEnableEXT);
X(vkCmdSetVertexInputEXT); X(vkCmdSetVertexInputEXT);
X(vkCmdSetColorWriteMaskEXT); X(vkCmdSetColorWriteMaskEXT);
X(vkCmdSetColorWriteEnableEXT);
X(vkCmdSetColorBlendEnableEXT); X(vkCmdSetColorBlendEnableEXT);
X(vkCmdSetColorBlendEquationEXT); X(vkCmdSetColorBlendEquationEXT);
X(vkCmdResolveImage); X(vkCmdResolveImage);

5
src/video_core/vulkan_common/vulkan_wrapper.h

@ -277,6 +277,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT{}; PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT{};
PFN_vkCmdSetViewport vkCmdSetViewport{}; PFN_vkCmdSetViewport vkCmdSetViewport{};
PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{}; PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{};
PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT{};
PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{}; PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{}; PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
PFN_vkCmdWaitEvents vkCmdWaitEvents{}; PFN_vkCmdWaitEvents vkCmdWaitEvents{};
@ -1589,6 +1590,10 @@ public:
dld->vkCmdSetColorWriteMaskEXT(handle, first, masks.size(), masks.data()); dld->vkCmdSetColorWriteMaskEXT(handle, first, masks.size(), masks.data());
} }
void SetColorWriteEnableEXT(u32 first, Span<VkBool32> enables) const noexcept {
dld->vkCmdSetColorWriteEnableEXT(handle, first, enables.size(), enables.data());
}
void SetColorBlendEnableEXT(u32 first, Span<VkBool32> enables) const noexcept { void SetColorBlendEnableEXT(u32 first, Span<VkBool32> enables) const noexcept {
dld->vkCmdSetColorBlendEnableEXT(handle, first, enables.size(), enables.data()); dld->vkCmdSetColorBlendEnableEXT(handle, first, enables.size(), enables.data());
} }

Loading…
Cancel
Save