vk_instance: Clean up extension management. (#2342)

This commit is contained in:
squidbus 2025-02-06 16:38:02 -08:00 committed by GitHub
parent 0d498f12b9
commit 1eb0affdea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 80 additions and 133 deletions

View file

@ -131,8 +131,7 @@ GraphicsPipeline::GraphicsPipeline(
vk::DynamicState::eStencilOpEXT, vk::DynamicState::eStencilOpEXT,
}; };
if (instance.IsColorWriteEnableSupported()) { if (instance.IsDynamicColorWriteMaskSupported()) {
dynamic_states.push_back(vk::DynamicState::eColorWriteEnableEXT);
dynamic_states.push_back(vk::DynamicState::eColorWriteMaskEXT); dynamic_states.push_back(vk::DynamicState::eColorWriteMaskEXT);
} }
if (instance.IsVertexInputDynamicState()) { if (instance.IsVertexInputDynamicState()) {
@ -241,7 +240,7 @@ GraphicsPipeline::GraphicsPipeline(
? LiverpoolToVK::BlendOp(control.alpha_func) ? LiverpoolToVK::BlendOp(control.alpha_func)
: color_blend, : color_blend,
.colorWriteMask = .colorWriteMask =
instance.IsColorWriteEnableSupported() instance.IsDynamicColorWriteMaskSupported()
? vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | ? vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA
: key.write_masks[i], : key.write_masks[i],

View file

@ -206,27 +206,23 @@ std::string Instance::GetDriverVersionName() {
} }
bool Instance::CreateDevice() { bool Instance::CreateDevice() {
const vk::StructureChain feature_chain = physical_device.getFeatures2< const vk::StructureChain feature_chain =
vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT, physical_device
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, .getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan12Features,
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT, vk::PhysicalDeviceRobustness2FeaturesEXT,
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT, vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT,
vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
vk::PhysicalDeviceColorWriteEnableFeaturesEXT, vk::PhysicalDeviceVulkan12Features,
vk::PhysicalDeviceVulkan13Features,
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR,
vk::PhysicalDeviceDepthClipControlFeaturesEXT, vk::PhysicalDeviceRobustness2FeaturesEXT,
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
const vk::StructureChain properties_chain = physical_device.getProperties2<
vk::PhysicalDeviceProperties2, vk::PhysicalDevicePortabilitySubsetPropertiesKHR,
vk::PhysicalDeviceExternalMemoryHostPropertiesEXT, vk::PhysicalDeviceVulkan11Properties,
vk::PhysicalDevicePushDescriptorPropertiesKHR, vk::PhysicalDeviceVulkan12Properties>();
subgroup_size = properties_chain.get<vk::PhysicalDeviceVulkan11Properties>().subgroupSize;
push_descriptor_props = properties_chain.get<vk::PhysicalDevicePushDescriptorPropertiesKHR>();
vk12_props = properties_chain.get<vk::PhysicalDeviceVulkan12Properties>();
LOG_INFO(Render_Vulkan, "Physical device subgroup size {}", subgroup_size);
features = feature_chain.get().features; features = feature_chain.get().features;
const vk::StructureChain properties_chain = physical_device.getProperties2<
vk::PhysicalDeviceProperties2, vk::PhysicalDeviceVulkan11Properties,
vk::PhysicalDeviceVulkan12Properties, vk::PhysicalDevicePushDescriptorPropertiesKHR>();
vk11_props = properties_chain.get<vk::PhysicalDeviceVulkan11Properties>();
vk12_props = properties_chain.get<vk::PhysicalDeviceVulkan12Properties>();
push_descriptor_props = properties_chain.get<vk::PhysicalDevicePushDescriptorPropertiesKHR>();
LOG_INFO(Render_Vulkan, "Physical device subgroup size {}", vk11_props.subgroupSize);
if (available_extensions.empty()) { if (available_extensions.empty()) {
LOG_CRITICAL(Render_Vulkan, "No extensions supported by device."); LOG_CRITICAL(Render_Vulkan, "No extensions supported by device.");
return false; return false;
@ -248,42 +244,43 @@ bool Instance::CreateDevice() {
return false; return false;
}; };
add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
workgroup_memory_explicit_layout =
add_extension(VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
fragment_shader_barycentric = add_extension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_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 bool calibrated_timestamps =
TRACY_GPU_ENABLED ? add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME) : false;
const bool robustness = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME);
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
// These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2
// with extensions. // with extensions.
if (Config::vkValidationEnabled() || Config::isRdocEnabled()) {
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
}
const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME); add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME);
add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
add_extension(VK_EXT_4444_FORMATS_EXTENSION_NAME); add_extension(VK_EXT_4444_FORMATS_EXTENSION_NAME);
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
dynamic_color_write_mask = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
if (dynamic_color_write_mask) {
dynamic_color_write_mask =
feature_chain.get<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>()
.extendedDynamicState3ColorWriteMask;
}
null_descriptor = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
if (null_descriptor) {
null_descriptor =
feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>().nullDescriptor;
}
maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
fragment_shader_barycentric = add_extension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME);
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
const bool calibrated_timestamps =
TRACY_GPU_ENABLED ? add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME) : false;
#ifdef __APPLE__ #ifdef __APPLE__
// Required by Vulkan spec if supported. // Required by Vulkan spec if supported.
@ -310,8 +307,7 @@ bool Instance::CreateDevice() {
return false; return false;
} }
static constexpr std::array<f32, 1> queue_priorities = {1.0f}; static constexpr std::array queue_priorities = {1.0f};
const vk::DeviceQueueCreateInfo queue_info = { const vk::DeviceQueueCreateInfo queue_info = {
.queueFamilyIndex = queue_family_index, .queueFamilyIndex = queue_family_index,
.queueCount = static_cast<u32>(queue_priorities.size()), .queueCount = static_cast<u32>(queue_priorities.size()),
@ -320,7 +316,6 @@ bool Instance::CreateDevice() {
const auto topology_list_restart_features = const auto topology_list_restart_features =
feature_chain.get<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>(); feature_chain.get<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
const auto vk12_features = feature_chain.get<vk::PhysicalDeviceVulkan12Features>(); const auto vk12_features = feature_chain.get<vk::PhysicalDeviceVulkan12Features>();
vk::StructureChain device_chain = { vk::StructureChain device_chain = {
vk::DeviceCreateInfo{ vk::DeviceCreateInfo{
@ -365,46 +360,42 @@ bool Instance::CreateDevice() {
.hostQueryReset = vk12_features.hostQueryReset, .hostQueryReset = vk12_features.hostQueryReset,
.timelineSemaphore = vk12_features.timelineSemaphore, .timelineSemaphore = vk12_features.timelineSemaphore,
}, },
vk::PhysicalDeviceMaintenance4FeaturesKHR{ // Vulkan 1.3 promoted extensions
.maintenance4 = true,
},
vk::PhysicalDeviceMaintenance5FeaturesKHR{
.maintenance5 = true,
},
vk::PhysicalDeviceDynamicRenderingFeaturesKHR{ vk::PhysicalDeviceDynamicRenderingFeaturesKHR{
.dynamicRendering = true, .dynamicRendering = true,
}, },
vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT{ vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT{
.shaderDemoteToHelperInvocation = true, .shaderDemoteToHelperInvocation = true,
}, },
vk::PhysicalDeviceCustomBorderColorFeaturesEXT{ vk::PhysicalDeviceSynchronization2Features{
.customBorderColors = true, .synchronization2 = true,
.customBorderColorWithoutFormat = true,
},
vk::PhysicalDeviceColorWriteEnableFeaturesEXT{
.colorWriteEnable = true,
}, },
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{ vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{
.extendedDynamicState = true, .extendedDynamicState = true,
}, },
vk::PhysicalDevice4444FormatsFeaturesEXT{
.formatA4B4G4R4 = true,
},
vk::PhysicalDeviceMaintenance4FeaturesKHR{
.maintenance4 = true,
},
// Other extensions
vk::PhysicalDeviceMaintenance5FeaturesKHR{
.maintenance5 = true,
},
vk::PhysicalDeviceCustomBorderColorFeaturesEXT{
.customBorderColors = true,
.customBorderColorWithoutFormat = true,
},
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{ vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{
.extendedDynamicState3ColorWriteMask = true, .extendedDynamicState3ColorWriteMask = true,
}, },
vk::PhysicalDeviceDepthClipControlFeaturesEXT{ vk::PhysicalDeviceDepthClipControlFeaturesEXT{
.depthClipControl = true, .depthClipControl = true,
}, },
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR{
.workgroupMemoryExplicitLayout = true,
.workgroupMemoryExplicitLayoutScalarBlockLayout = true,
.workgroupMemoryExplicitLayout8BitAccess = true,
.workgroupMemoryExplicitLayout16BitAccess = true,
},
vk::PhysicalDeviceRobustness2FeaturesEXT{ vk::PhysicalDeviceRobustness2FeaturesEXT{
.nullDescriptor = true, .nullDescriptor = true,
}, },
vk::PhysicalDeviceSynchronization2Features{
.synchronization2 = true,
},
vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{ vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT{
.vertexInputDynamicState = true, .vertexInputDynamicState = true,
}, },
@ -433,31 +424,21 @@ bool Instance::CreateDevice() {
if (!custom_border_color) { if (!custom_border_color) {
device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>();
} }
if (!color_write_en) { if (!dynamic_color_write_mask) {
device_chain.unlink<vk::PhysicalDeviceColorWriteEnableFeaturesEXT>();
device_chain.unlink<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT>();
} }
if (!depth_clip_control) { if (!depth_clip_control) {
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
} }
if (!workgroup_memory_explicit_layout) { if (!null_descriptor) {
device_chain.unlink<vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR>();
}
if (!list_restart) {
device_chain.unlink<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
}
if (robustness) {
null_descriptor =
feature_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>().nullDescriptor;
device_chain.get<vk::PhysicalDeviceRobustness2FeaturesEXT>().nullDescriptor =
null_descriptor;
} else {
null_descriptor = false;
device_chain.unlink<vk::PhysicalDeviceRobustness2FeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceRobustness2FeaturesEXT>();
} }
if (!vertex_input_dynamic_state) { if (!vertex_input_dynamic_state) {
device_chain.unlink<vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT>(); device_chain.unlink<vk::PhysicalDeviceVertexInputDynamicStateFeaturesEXT>();
} }
if (!list_restart) {
device_chain.unlink<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
}
if (!fragment_shader_barycentric) { if (!fragment_shader_barycentric) {
device_chain.unlink<vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR>(); device_chain.unlink<vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR>();
} }

View file

@ -89,34 +89,19 @@ public:
return custom_border_color; return custom_border_color;
} }
/// Returns true when VK_EXT_fragment_shader_interlock is supported
bool IsFragmentShaderInterlockSupported() const {
return fragment_shader_interlock;
}
/// Returns true when VK_EXT_pipeline_creation_cache_control is supported
bool IsPipelineCreationCacheControlSupported() const {
return pipeline_creation_cache_control;
}
/// Returns true when VK_EXT_shader_stencil_export is supported /// Returns true when VK_EXT_shader_stencil_export is supported
bool IsShaderStencilExportSupported() const { bool IsShaderStencilExportSupported() const {
return shader_stencil_export; return shader_stencil_export;
} }
/// Returns true when VK_EXT_external_memory_host is supported
bool IsExternalMemoryHostSupported() const {
return external_memory_host;
}
/// Returns true when VK_EXT_depth_clip_control is supported /// Returns true when VK_EXT_depth_clip_control is supported
bool IsDepthClipControlSupported() const { bool IsDepthClipControlSupported() const {
return depth_clip_control; return depth_clip_control;
} }
/// Returns true when VK_EXT_color_write_enable is supported /// Returns true when dynamic color write mask state is supported
bool IsColorWriteEnableSupported() const { bool IsDynamicColorWriteMaskSupported() const {
return color_write_en; return dynamic_color_write_mask;
} }
/// Returns true when VK_EXT_vertex_input_dynamic_state is supported. /// Returns true when VK_EXT_vertex_input_dynamic_state is supported.
@ -236,7 +221,7 @@ public:
/// Returns the subgroup size of the selected physical device. /// Returns the subgroup size of the selected physical device.
u32 SubgroupSize() const { u32 SubgroupSize() const {
return subgroup_size; return vk11_props.subgroupSize;
} }
/// Returns the maximum size of compute shared memory. /// Returns the maximum size of compute shared memory.
@ -274,11 +259,6 @@ public:
return features.shaderClipDistance; return features.shaderClipDistance;
} }
/// Returns the minimum imported host pointer alignment
u64 GetMinImportedHostPointerAlignment() const {
return min_imported_host_pointer_alignment;
}
u32 GetMaxViewportWidth() const { u32 GetMaxViewportWidth() const {
return properties.limits.maxViewportDimensions[0]; return properties.limits.maxViewportDimensions[0];
} }
@ -316,8 +296,9 @@ private:
vk::PhysicalDevice physical_device; vk::PhysicalDevice physical_device;
vk::UniqueDevice device; vk::UniqueDevice device;
vk::PhysicalDeviceProperties properties; vk::PhysicalDeviceProperties properties;
vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props; vk::PhysicalDeviceVulkan11Properties vk11_props;
vk::PhysicalDeviceVulkan12Properties vk12_props; vk::PhysicalDeviceVulkan12Properties vk12_props;
vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props;
vk::PhysicalDeviceFeatures features; vk::PhysicalDeviceFeatures features;
vk::DriverIdKHR driver_id; vk::DriverIdKHR driver_id;
vk::UniqueDebugUtilsMessengerEXT debug_callback{}; vk::UniqueDebugUtilsMessengerEXT debug_callback{};
@ -330,27 +311,19 @@ private:
std::unordered_map<vk::Format, vk::FormatProperties3> format_properties; std::unordered_map<vk::Format, vk::FormatProperties3> format_properties;
TracyVkCtx profiler_context{}; TracyVkCtx profiler_context{};
u32 queue_family_index{0}; u32 queue_family_index{0};
bool image_view_reinterpretation{true};
bool timeline_semaphores{};
bool custom_border_color{}; bool custom_border_color{};
bool fragment_shader_interlock{};
bool pipeline_creation_cache_control{};
bool fragment_shader_barycentric{}; bool fragment_shader_barycentric{};
bool shader_stencil_export{};
bool external_memory_host{};
bool depth_clip_control{}; bool depth_clip_control{};
bool workgroup_memory_explicit_layout{}; bool dynamic_color_write_mask{};
bool color_write_en{};
bool vertex_input_dynamic_state{}; bool vertex_input_dynamic_state{};
bool null_descriptor{}; bool null_descriptor{};
bool maintenance5{}; bool maintenance5{};
bool list_restart{}; bool list_restart{};
bool legacy_vertex_attributes{}; bool legacy_vertex_attributes{};
bool shader_stencil_export{};
bool image_load_store_lod{}; bool image_load_store_lod{};
bool amd_gcn_shader{}; bool amd_gcn_shader{};
bool tooling_info{}; bool tooling_info{};
u64 min_imported_host_pointer_alignment{};
u32 subgroup_size{};
}; };
} // namespace Vulkan } // namespace Vulkan

View file

@ -1062,14 +1062,8 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
const auto cmdbuf = scheduler.CommandBuffer(); const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setBlendConstants(&regs.blend_constants.red); cmdbuf.setBlendConstants(&regs.blend_constants.red);
if (instance.IsColorWriteEnableSupported()) { if (instance.IsDynamicColorWriteMaskSupported()) {
const auto& write_masks = pipeline.GetWriteMasks(); cmdbuf.setColorWriteMaskEXT(0, pipeline.GetWriteMasks());
std::array<vk::Bool32, Liverpool::NumColorBuffers> write_ens{};
std::transform(write_masks.cbegin(), write_masks.cend(), write_ens.begin(),
[](auto in) { return in ? vk::True : vk::False; });
cmdbuf.setColorWriteEnableEXT(write_ens);
cmdbuf.setColorWriteMaskEXT(0, write_masks);
} }
if (regs.depth_control.depth_bounds_enable) { if (regs.depth_control.depth_bounds_enable) {
cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max); cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);