mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-10 05:38:49 +00:00
renderer_vulkan: Resore color write dynamic state (#3453)
This commit is contained in:
@@ -127,6 +127,14 @@ union CompMapping {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u32 ApplyMask(u32 mask) const {
|
||||||
|
u32 swizzled_mask{};
|
||||||
|
for (u32 i = 0; i < 4; ++i) {
|
||||||
|
swizzled_mask |= ((mask >> i) & 1) << Map(i);
|
||||||
|
}
|
||||||
|
return swizzled_mask;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] CompMapping Inverse() const {
|
[[nodiscard]] CompMapping Inverse() const {
|
||||||
CompMapping result{};
|
CompMapping result{};
|
||||||
InverseSingle(result.r, CompSwizzle::Red);
|
InverseSingle(result.r, CompSwizzle::Red);
|
||||||
|
|||||||
@@ -168,6 +168,9 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable);
|
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable);
|
||||||
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
||||||
}
|
}
|
||||||
|
if (instance.IsDynamicColorWriteMaskSupported()) {
|
||||||
|
dynamic_states.push_back(vk::DynamicState::eColorWriteMaskEXT);
|
||||||
|
}
|
||||||
if (instance.IsVertexInputDynamicState()) {
|
if (instance.IsVertexInputDynamicState()) {
|
||||||
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
|
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
|
||||||
} else if (!vertex_bindings.empty()) {
|
} else if (!vertex_bindings.empty()) {
|
||||||
@@ -288,7 +291,11 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
.alphaBlendOp = control.separate_alpha_blend
|
.alphaBlendOp = control.separate_alpha_blend
|
||||||
? LiverpoolToVK::BlendOp(control.alpha_func)
|
? LiverpoolToVK::BlendOp(control.alpha_func)
|
||||||
: color_blend,
|
: color_blend,
|
||||||
.colorWriteMask = vk::ColorComponentFlags{key.write_masks[i]},
|
.colorWriteMask =
|
||||||
|
instance.IsDynamicColorWriteMaskSupported()
|
||||||
|
? vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||||
|
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA
|
||||||
|
: key.write_masks[i],
|
||||||
};
|
};
|
||||||
|
|
||||||
// On GCN GPU there is an additional mask which allows to control color components exported
|
// On GCN GPU there is an additional mask which allows to control color components exported
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct GraphicsPipelineKey {
|
|||||||
u32 num_color_attachments;
|
u32 num_color_attachments;
|
||||||
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
||||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||||
std::array<u32, Liverpool::NumColorBuffers> write_masks;
|
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
||||||
Liverpool::ColorBufferMask cb_shader_mask;
|
Liverpool::ColorBufferMask cb_shader_mask;
|
||||||
Liverpool::ColorControl::LogicOp logic_op;
|
Liverpool::ColorControl::LogicOp logic_op;
|
||||||
u32 num_samples;
|
u32 num_samples;
|
||||||
@@ -80,6 +80,10 @@ public:
|
|||||||
return fetch_shader;
|
return fetch_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto GetWriteMasks() const {
|
||||||
|
return key.write_masks;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetMrtMask() const {
|
u32 GetMrtMask() const {
|
||||||
return key.mrt_mask;
|
return key.mrt_mask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,6 +255,13 @@ bool Instance::CreateDevice() {
|
|||||||
// Optional
|
// Optional
|
||||||
maintenance_8 = add_extension(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
|
maintenance_8 = add_extension(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
|
||||||
depth_range_unrestricted = add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
depth_range_unrestricted = add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||||
|
dynamic_state_3 = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||||
|
if (dynamic_state_3) {
|
||||||
|
dynamic_state_3_features =
|
||||||
|
feature_chain.get<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
|
||||||
|
LOG_INFO(Render_Vulkan, "- extendedDynamicState3ColorWriteMask: {}",
|
||||||
|
dynamic_state_3_features.extendedDynamicState3ColorWriteMask);
|
||||||
|
}
|
||||||
robustness2 = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
robustness2 = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
||||||
if (robustness2) {
|
if (robustness2) {
|
||||||
robustness2_features = feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
robustness2_features = feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
||||||
@@ -419,6 +426,10 @@ bool Instance::CreateDevice() {
|
|||||||
.customBorderColors = true,
|
.customBorderColors = true,
|
||||||
.customBorderColorWithoutFormat = true,
|
.customBorderColorWithoutFormat = true,
|
||||||
},
|
},
|
||||||
|
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{
|
||||||
|
.extendedDynamicState3ColorWriteMask =
|
||||||
|
dynamic_state_3_features.extendedDynamicState3ColorWriteMask,
|
||||||
|
},
|
||||||
vk::PhysicalDeviceDepthClipControlFeaturesEXT{
|
vk::PhysicalDeviceDepthClipControlFeaturesEXT{
|
||||||
.depthClipControl = true,
|
.depthClipControl = true,
|
||||||
},
|
},
|
||||||
@@ -494,6 +505,9 @@ bool Instance::CreateDevice() {
|
|||||||
if (!custom_border_color) {
|
if (!custom_border_color) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>();
|
||||||
}
|
}
|
||||||
|
if (!dynamic_state_3) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
|
||||||
|
}
|
||||||
if (!depth_clip_control) {
|
if (!depth_clip_control) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ public:
|
|||||||
return depth_range_unrestricted;
|
return depth_range_unrestricted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true when the extendedDynamicState3ColorWriteMask feature o
|
||||||
|
/// VK_EXT_extended_dynamic_state3 is supported.
|
||||||
|
bool IsDynamicColorWriteMaskSupported() const {
|
||||||
|
return dynamic_state_3 && dynamic_state_3_features.extendedDynamicState3ColorWriteMask;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when VK_EXT_vertex_input_dynamic_state is supported.
|
/// Returns true when VK_EXT_vertex_input_dynamic_state is supported.
|
||||||
bool IsVertexInputDynamicState() const {
|
bool IsVertexInputDynamicState() const {
|
||||||
return vertex_input_dynamic_state;
|
return vertex_input_dynamic_state;
|
||||||
@@ -433,6 +439,7 @@ private:
|
|||||||
vk::PhysicalDeviceFeatures features;
|
vk::PhysicalDeviceFeatures features;
|
||||||
vk::PhysicalDeviceVulkan12Features vk12_features;
|
vk::PhysicalDeviceVulkan12Features vk12_features;
|
||||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features;
|
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features;
|
||||||
|
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT dynamic_state_3_features;
|
||||||
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features;
|
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features;
|
||||||
vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT shader_atomic_float2_features;
|
vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT shader_atomic_float2_features;
|
||||||
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR
|
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR
|
||||||
@@ -453,6 +460,7 @@ private:
|
|||||||
bool amd_shader_explicit_vertex_parameter{};
|
bool amd_shader_explicit_vertex_parameter{};
|
||||||
bool depth_clip_control{};
|
bool depth_clip_control{};
|
||||||
bool depth_clip_enable{};
|
bool depth_clip_enable{};
|
||||||
|
bool dynamic_state_3{};
|
||||||
bool depth_range_unrestricted{};
|
bool depth_range_unrestricted{};
|
||||||
bool vertex_input_dynamic_state{};
|
bool vertex_input_dynamic_state{};
|
||||||
bool robustness2{};
|
bool robustness2{};
|
||||||
|
|||||||
@@ -345,10 +345,8 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
!col_buf.info.blend_bypass);
|
!col_buf.info.blend_bypass);
|
||||||
|
|
||||||
// Apply swizzle to target mask
|
// Apply swizzle to target mask
|
||||||
const auto& swizzle = key.color_buffers[cb].swizzle;
|
key.write_masks[cb] =
|
||||||
for (u32 i = 0; i < 4; ++i) {
|
vk::ColorComponentFlags{key.color_buffers[cb].swizzle.ApplyMask(target_mask)};
|
||||||
key.write_masks[cb] |= ((target_mask >> i) & 1) << swizzle.Map(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile and bind shader stages
|
// Compile and bind shader stages
|
||||||
|
|||||||
@@ -1097,6 +1097,7 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
|||||||
|
|
||||||
auto& dynamic_state = scheduler.GetDynamicState();
|
auto& dynamic_state = scheduler.GetDynamicState();
|
||||||
dynamic_state.SetBlendConstants(liverpool->regs.blend_constants);
|
dynamic_state.SetBlendConstants(liverpool->regs.blend_constants);
|
||||||
|
dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks());
|
||||||
|
|
||||||
// Commit new dynamic state to the command buffer.
|
// Commit new dynamic state to the command buffer.
|
||||||
dynamic_state.Commit(instance, scheduler.CommandBuffer());
|
dynamic_state.Commit(instance, scheduler.CommandBuffer());
|
||||||
|
|||||||
@@ -323,6 +323,12 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
|
|||||||
dirty_state.blend_constants = false;
|
dirty_state.blend_constants = false;
|
||||||
cmdbuf.setBlendConstants(blend_constants.data());
|
cmdbuf.setBlendConstants(blend_constants.data());
|
||||||
}
|
}
|
||||||
|
if (dirty_state.color_write_masks) {
|
||||||
|
dirty_state.color_write_masks = false;
|
||||||
|
if (instance.IsDynamicColorWriteMaskSupported()) {
|
||||||
|
cmdbuf.setColorWriteMaskEXT(0, color_write_masks);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (dirty_state.line_width) {
|
if (dirty_state.line_width) {
|
||||||
dirty_state.line_width = false;
|
dirty_state.line_width = false;
|
||||||
cmdbuf.setLineWidth(line_width);
|
cmdbuf.setLineWidth(line_width);
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ struct DynamicState {
|
|||||||
bool front_face : 1;
|
bool front_face : 1;
|
||||||
|
|
||||||
bool blend_constants : 1;
|
bool blend_constants : 1;
|
||||||
|
bool color_write_masks : 1;
|
||||||
bool line_width : 1;
|
bool line_width : 1;
|
||||||
} dirty_state{};
|
} dirty_state{};
|
||||||
|
|
||||||
@@ -143,6 +144,7 @@ struct DynamicState {
|
|||||||
vk::FrontFace front_face{};
|
vk::FrontFace front_face{};
|
||||||
|
|
||||||
std::array<float, 4> blend_constants{};
|
std::array<float, 4> blend_constants{};
|
||||||
|
ColorWriteMasks color_write_masks{};
|
||||||
float line_width{};
|
float line_width{};
|
||||||
|
|
||||||
/// Commits the dynamic state to the provided command buffer.
|
/// Commits the dynamic state to the provided command buffer.
|
||||||
@@ -306,6 +308,13 @@ struct DynamicState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetColorWriteMasks(const ColorWriteMasks& color_write_masks_) {
|
||||||
|
if (!std::ranges::equal(color_write_masks, color_write_masks_)) {
|
||||||
|
color_write_masks = color_write_masks_;
|
||||||
|
dirty_state.color_write_masks = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetLineWidth(const float width) {
|
void SetLineWidth(const float width) {
|
||||||
if (line_width != width) {
|
if (line_width != width) {
|
||||||
line_width = width;
|
line_width = width;
|
||||||
|
|||||||
Reference in New Issue
Block a user