mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-16 21:33:01 +00:00
[vulkan] Implementation color write enable + color border swizzle
This commit is contained in:
@@ -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_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);
|
||||
color_write_enable_dynamic.Assign(features.has_color_write_enable ? 1 : 0);
|
||||
dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0);
|
||||
xfb_enabled.Assign(regs.transform_feedback_enabled != 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;
|
||||
for (size_t index = 0; index < attachments.size(); ++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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ struct DynamicFeatures {
|
||||
bool has_dynamic_state3_logic_op_enable;
|
||||
bool has_dynamic_state3_line_stipple_enable;
|
||||
bool has_dynamic_vertex_input;
|
||||
bool has_color_write_enable;
|
||||
bool has_provoking_vertex;
|
||||
bool has_provoking_vertex_first_mode;
|
||||
bool has_provoking_vertex_last_mode;
|
||||
@@ -208,6 +209,7 @@ struct FixedPipelineState {
|
||||
BitField<12, 2, u32> tessellation_spacing;
|
||||
BitField<14, 1, u32> tessellation_clockwise;
|
||||
BitField<15, 5, u32> patch_control_points_minus_one;
|
||||
BitField<20, 1, u32> color_write_enable_dynamic;
|
||||
|
||||
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
|
||||
BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode;
|
||||
|
||||
@@ -869,15 +869,13 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
};
|
||||
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) {
|
||||
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) {
|
||||
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());
|
||||
}
|
||||
|
||||
// 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)
|
||||
if (key.state.extended_dynamic_state_3_enables) {
|
||||
if (device.SupportsDynamicState3DepthClampEnable()) {
|
||||
|
||||
@@ -500,6 +500,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||
device.IsExtExtendedDynamicState3BlendingSupported();
|
||||
dynamic_features.has_extended_dynamic_state_3_enables =
|
||||
device.IsExtExtendedDynamicState3EnablesSupported();
|
||||
dynamic_features.has_color_write_enable =
|
||||
device.IsExtColorWriteEnableSupported();
|
||||
dynamic_features.has_dynamic_state3_depth_clamp_enable =
|
||||
dynamic_features.has_extended_dynamic_state_3_enables &&
|
||||
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 ||
|
||||
(key.state.extended_dynamic_state_3_enables != 0) !=
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1080,6 +1080,8 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
|
||||
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
|
||||
UpdateBlending(regs);
|
||||
} else if (device.IsExtColorWriteEnableSupported()) {
|
||||
UpdateColorWriteEnable(regs);
|
||||
}
|
||||
|
||||
if (device.IsExtVertexInputDynamicStateSupported()) {
|
||||
@@ -1094,7 +1096,6 @@ void RasterizerVulkan::HandleTransformFeedback() {
|
||||
|
||||
const auto& regs = maxwell3d->regs;
|
||||
if (!device.IsExtTransformFeedbackSupported()) {
|
||||
// If the guest enabled transform feedback, warn once that the device lacks support.
|
||||
if (regs.transform_feedback_enabled != 0) {
|
||||
std::call_once(warn_unsupported, [&] {
|
||||
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) {
|
||||
if (!state_tracker.TouchStencilTestEnable()) {
|
||||
return;
|
||||
|
||||
@@ -191,6 +191,7 @@ private:
|
||||
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateLogicOp(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);
|
||||
|
||||
|
||||
@@ -2297,12 +2297,15 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
|
||||
const void* pnext = nullptr;
|
||||
if (has_custom_border_colors) {
|
||||
pnext = &border_ci;
|
||||
// Log extension usage for custom border color
|
||||
if (GPU::Logging::IsActive()) {
|
||||
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
|
||||
"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{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,
|
||||
.pNext = pnext,
|
||||
|
||||
@@ -1170,6 +1170,21 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||
}
|
||||
|
||||
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
|
||||
if (extensions.custom_border_color) {
|
||||
extensions.custom_border_color =
|
||||
|
||||
@@ -50,6 +50,8 @@ 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, 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, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \
|
||||
FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \
|
||||
@@ -584,6 +586,21 @@ FN_MAX_LIMIT_LIST
|
||||
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.
|
||||
bool IsExtExtendedDynamicStateSupported() const {
|
||||
return extensions.extended_dynamic_state;
|
||||
|
||||
@@ -162,6 +162,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||
X(vkCmdSetStencilTestEnableEXT);
|
||||
X(vkCmdSetVertexInputEXT);
|
||||
X(vkCmdSetColorWriteMaskEXT);
|
||||
X(vkCmdSetColorWriteEnableEXT);
|
||||
X(vkCmdSetColorBlendEnableEXT);
|
||||
X(vkCmdSetColorBlendEquationEXT);
|
||||
X(vkCmdResolveImage);
|
||||
|
||||
@@ -277,6 +277,7 @@ struct DeviceDispatch : InstanceDispatch {
|
||||
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT{};
|
||||
PFN_vkCmdSetViewport vkCmdSetViewport{};
|
||||
PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT{};
|
||||
PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT{};
|
||||
PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
|
||||
PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
|
||||
PFN_vkCmdWaitEvents vkCmdWaitEvents{};
|
||||
@@ -1589,6 +1590,10 @@ public:
|
||||
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 {
|
||||
dld->vkCmdSetColorBlendEnableEXT(handle, first, enables.size(), enables.data());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user