Support VK_EXT_load_store_op_none & color_write_enable. Closes #2363

* These are added together because VK_EXT_load_store_op_none is easier to test
  in a realistic fashion using VK_EXT_color_write_enable
This commit is contained in:
baldurk
2021-10-22 14:48:58 +01:00
parent 5d1dc8f48a
commit 7a4e68959f
24 changed files with 550 additions and 32 deletions
+2 -2
View File
@@ -26,6 +26,7 @@ Maintainers can update this file by updating vk.xml in this folder and running `
* `VK_EXT_astc_decode_mode`
* `VK_EXT_buffer_device_address`
* `VK_EXT_calibrated_timestamps`
* `VK_EXT_color_write_enable`
* `VK_EXT_conditional_rendering`
* `VK_EXT_conservative_rasterization`
* `VK_EXT_custom_border_color`
@@ -55,6 +56,7 @@ Maintainers can update this file by updating vk.xml in this folder and running `
* `VK_EXT_index_type_uint8`
* `VK_EXT_inline_uniform_block`
* `VK_EXT_line_rasterization`
* `VK_EXT_load_store_op_none`
* `VK_EXT_memory_budget`
* `VK_EXT_memory_priority`
* `VK_EXT_metal_surface`
@@ -220,12 +222,10 @@ Ray tracing extensions are now standard and will likely be supported at some poi
* `VK_EXT_acquire_drm_display`
* `VK_EXT_blend_operation_advanced`
* `VK_EXT_border_color_swizzle`
* `VK_EXT_color_write_enable`
* `VK_EXT_device_memory_report`
* `VK_EXT_extended_dynamic_state2`
* `VK_EXT_external_memory_host`
* `VK_EXT_image_drm_format_modifier`
* `VK_EXT_load_store_op_none`
* `VK_EXT_multi_draw`
* `VK_EXT_pageable_device_local_memory`
* `VK_EXT_physical_device_drm`
+5
View File
@@ -715,6 +715,7 @@ enum class VulkanChunk : uint32_t
vkCmdWriteTimestamp2KHR,
vkQueueSubmit2KHR,
vkCmdWriteBufferMarker2AMD,
vkCmdSetColorWriteEnableEXT,
Max,
};
@@ -917,6 +918,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceASTCDecodeFeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceBufferDeviceAddressFeatures);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceCoherentMemoryFeaturesAMD);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceColorWriteEnableFeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceConditionalRenderingFeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceConservativeRasterizationPropertiesEXT);
@@ -1026,6 +1028,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR);
DECLARE_REFLECTION_STRUCT(VkPipelineCacheCreateInfo);
DECLARE_REFLECTION_STRUCT(VkPipelineColorBlendStateCreateInfo);
DECLARE_REFLECTION_STRUCT(VkPipelineColorWriteCreateInfoEXT);
DECLARE_REFLECTION_STRUCT(VkPipelineCreationFeedbackCreateInfoEXT);
DECLARE_REFLECTION_STRUCT(VkPipelineDepthStencilStateCreateInfo);
DECLARE_REFLECTION_STRUCT(VkPipelineDiscardRectangleStateCreateInfoEXT);
@@ -1262,6 +1265,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDevice16BitStorageFeatures);
DECLARE_DESERIALISE_TYPE(VkPhysicalDevice8BitStorageFeatures);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceASTCDecodeFeaturesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceCoherentMemoryFeaturesAMD);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceColorWriteEnableFeaturesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceConditionalRenderingFeaturesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceConservativeRasterizationPropertiesEXT);
@@ -1371,6 +1375,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR);
DECLARE_DESERIALISE_TYPE(VkPipelineCacheCreateInfo);
DECLARE_DESERIALISE_TYPE(VkPipelineColorBlendStateCreateInfo);
DECLARE_DESERIALISE_TYPE(VkPipelineColorWriteCreateInfoEXT);
DECLARE_DESERIALISE_TYPE(VkPipelineCreationFeedbackCreateInfoEXT);
DECLARE_DESERIALISE_TYPE(VkPipelineDepthStencilStateCreateInfo);
DECLARE_DESERIALISE_TYPE(VkPipelineDiscardRectangleStateCreateInfoEXT);
+8
View File
@@ -878,6 +878,9 @@ static const VkExtensionProperties supportedExtensions[] = {
{
VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION,
},
{
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME, VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION,
},
{
VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME, VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION,
},
@@ -965,6 +968,9 @@ static const VkExtensionProperties supportedExtensions[] = {
{
VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME, VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION,
},
{
VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME, VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION,
},
{
VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, VK_EXT_LINE_RASTERIZATION_SPEC_VERSION,
},
@@ -3478,6 +3484,8 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
case VulkanChunk::vkCmdWriteBufferMarker2AMD:
return Serialise_vkCmdWriteBufferMarker2AMD(ser, VK_NULL_HANDLE, VK_PIPELINE_STAGE_2_NONE_KHR,
VK_NULL_HANDLE, 0, 0);
case VulkanChunk::vkCmdSetColorWriteEnableEXT:
return Serialise_vkCmdSetColorWriteEnableEXT(ser, VK_NULL_HANDLE, 0, NULL);
// chunks that are reserved but not yet serialised
case VulkanChunk::vkResetCommandPool:
+7
View File
@@ -407,6 +407,7 @@ private:
bool m_SeparateDepthStencil = false;
bool m_NULLDescriptorsAllowed = false;
bool m_ExtendedDynState = false;
bool m_DynColorWrite = false;
PFN_vkSetDeviceLoaderData m_SetDeviceLoaderData;
@@ -1122,6 +1123,7 @@ public:
bool SeparateDepthStencil() const { return m_SeparateDepthStencil; }
bool NULLDescriptorsAllowed() const { return m_NULLDescriptorsAllowed; }
bool ExtendedDynamicState() const { return m_ExtendedDynState; }
bool DynamicColorWrite() const { return m_DynColorWrite; }
VulkanRenderState &GetRenderState() { return m_RenderState; }
void SetActionCB(VulkanActionCallback *cb) { m_ActionCallback = cb; }
void SetSubmitChain(void *submitChain) { m_SubmitChain = submitChain; }
@@ -2473,4 +2475,9 @@ public:
const VkDeviceImageMemoryRequirementsKHR *pInfo,
uint32_t *pSparseMemoryRequirementCount,
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements);
// VK_EXT_color_write_enable
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdSetColorWriteEnableEXT, VkCommandBuffer commandBuffer,
uint32_t attachmentCount, const VkBool32 *pColorWriteEnables);
};
+9 -2
View File
@@ -529,7 +529,8 @@
DeclExt(KHR_copy_commands2); \
DeclExt(KHR_synchronization2); \
DeclExt(KHR_present_wait); \
DeclExt(KHR_maintenance4);
DeclExt(KHR_maintenance4); \
DeclExt(EXT_color_write_enable);
// for simplicity and since the check itself is platform agnostic,
// these aren't protected in platform defines
@@ -629,7 +630,10 @@
CheckExt(EXT_private_data, VKXX); \
CheckExt(EXT_extended_dynamic_state, VKXX); \
CheckExt(KHR_copy_commands2, VKXX); \
CheckExt(KHR_synchronization2, VKXX);
CheckExt(KHR_synchronization2, VKXX); \
CheckExt(KHR_present_wait, VKXX); \
CheckExt(KHR_maintenance4, VKXX); \
CheckExt(EXT_color_write_enable, VKXX);
#define HookInitVulkanInstanceExts_PhysDev() \
HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \
@@ -874,6 +878,7 @@
HookInitExtension(KHR_maintenance4, GetDeviceBufferMemoryRequirementsKHR); \
HookInitExtension(KHR_maintenance4, GetDeviceImageMemoryRequirementsKHR); \
HookInitExtension(KHR_maintenance4, GetDeviceImageSparseMemoryRequirementsKHR); \
HookInitExtension(EXT_color_write_enable, CmdSetColorWriteEnableEXT); \
/* No GetQueueCheckpointData2NV without VK_NV_device_diagnostic_checkpoints */ \
HookInitExtension_Device_Win32(); \
HookInitExtension_Device_Linux(); \
@@ -1570,6 +1575,8 @@
const VkDeviceImageMemoryRequirementsKHR *, pInfo, uint32_t *, \
pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 *, \
pSparseMemoryRequirements); \
HookDefine3(void, vkCmdSetColorWriteEnableEXT, VkCommandBuffer, commandBuffer, uint32_t, \
attachmentCount, const VkBool32 *, pColorWriteEnables); \
HookDefine_Win32(); \
HookDefine_Linux(); \
HookDefine_GGP(); \
+16
View File
@@ -699,6 +699,22 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan,
attachments.clear();
}
// this struct probably will never get used, since the user could just set the colorWriteMask
// above to 0. It's really only useful for specifying how the dynamic state works. However just
// for completeness...
const VkPipelineColorWriteCreateInfoEXT *colorWriteEnable =
(const VkPipelineColorWriteCreateInfoEXT *)FindNextStruct(
pCreateInfo->pRasterizationState, VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT);
if(colorWriteEnable)
{
RDCASSERTEQUAL(attachments.size(), colorWriteEnable->attachmentCount);
for(size_t i = 0; i < attachments.size() && i < colorWriteEnable->attachmentCount; i++)
{
if(!colorWriteEnable->pColorWriteEnables[i])
attachments[i].channelWriteMask = 0;
}
}
}
void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
+2 -2
View File
@@ -374,7 +374,7 @@ struct VulkanCreationInfo
VkLogicOp logicOp;
float blendConst[4];
struct Attachment
struct CBAttachment
{
bool blendEnable;
@@ -387,7 +387,7 @@ struct VulkanCreationInfo
uint8_t channelWriteMask;
};
rdcarray<Attachment> attachments;
rdcarray<CBAttachment> attachments;
// VkPipelineDynamicStateCreateInfo
bool dynamicStates[VkDynamicCount];
+4 -2
View File
@@ -203,6 +203,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
VkPhysicalDeviceBufferDeviceAddressFeatures); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD, \
VkPhysicalDeviceCoherentMemoryFeaturesAMD); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT, \
VkPhysicalDeviceColorWriteEnableFeaturesEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV, \
VkPhysicalDeviceComputeShaderDerivativesFeaturesNV); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT, \
@@ -416,6 +418,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
VkPipelineCreationFeedbackCreateInfoEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, \
VkPipelineColorBlendStateCreateInfo); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, \
VkPipelineColorWriteCreateInfoEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT, \
VkPipelineRasterizationDepthClipStateCreateInfoEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, \
@@ -726,7 +730,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: \
@@ -775,7 +778,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT: \
case VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT: \
case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD: \
case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: \
case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: \
+5
View File
@@ -2766,6 +2766,11 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
state.front.passOp, state.front.depthFailOp,
state.front.compareOp);
}
else if(d == VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT)
{
vt->CmdSetColorWriteEnableEXT(Unwrap(cmd), (uint32_t)state.colorWriteEnable.size(),
state.colorWriteEnable.data());
}
}
if(fmt.indexByteStride)
@@ -687,6 +687,15 @@ protected:
descs[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
descs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
descs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
if(rpInfo.attachments[i].loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT)
descs[i].loadOp = VK_ATTACHMENT_LOAD_OP_NONE_EXT;
if(rpInfo.attachments[i].storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT)
descs[i].storeOp = VK_ATTACHMENT_STORE_OP_NONE_EXT;
if(rpInfo.attachments[i].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT)
descs[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_NONE_EXT;
if(rpInfo.attachments[i].stencilStoreOp == VK_ATTACHMENT_STORE_OP_NONE_EXT)
descs[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_NONE_EXT;
descs[i].initialLayout = rpInfo.attachments[i].initialLayout;
descs[i].finalLayout = rpInfo.attachments[i].finalLayout;
}
+3
View File
@@ -1452,6 +1452,9 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
MakeBlendOp(p.attachments[i].alphaBlend.Operation);
ret.colorBlend.blends[i].writeMask = p.attachments[i].channelWriteMask;
if(i < state.colorWriteEnable.size() && !state.colorWriteEnable[i])
ret.colorBlend.blends[i].writeMask = 0;
}
ret.colorBlend.blendFactor = state.blendConst;
+40 -4
View File
@@ -556,6 +556,12 @@ SERIALISE_VK_HANDLES();
/* VK_EXT_calibrated_timestamps */ \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, VkCalibratedTimestampInfoEXT) \
\
/* VK_EXT_color_write_enable */ \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT, \
VkPhysicalDeviceColorWriteEnableFeaturesEXT) \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, \
VkPipelineColorWriteCreateInfoEXT) \
\
/* VK_EXT_conditional_rendering */ \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT, \
VkCommandBufferInheritanceConditionalRenderingInfoEXT) \
@@ -1256,10 +1262,6 @@ SERIALISE_VK_HANDLES();
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT) \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT) \
\
/* VK_EXT_color_write_enable */ \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT) \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT) \
\
/* VK_EXT_device_memory_report */ \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT) \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT) \
@@ -7695,6 +7697,38 @@ void Deserialise(const VkCalibratedTimestampInfoEXT &el)
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPhysicalDeviceColorWriteEnableFeaturesEXT &el)
{
RDCASSERT(ser.IsReading() ||
el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(colorWriteEnable);
}
template <>
void Deserialise(const VkPhysicalDeviceColorWriteEnableFeaturesEXT &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPipelineColorWriteCreateInfoEXT &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(attachmentCount);
SERIALISE_MEMBER_ARRAY(pColorWriteEnables, attachmentCount);
}
template <>
void Deserialise(const VkPipelineColorWriteCreateInfoEXT &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSwapchainCounterCreateInfoEXT &el)
{
@@ -9731,6 +9765,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceASTCDecodeFeaturesEXT)
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceBufferDeviceAddressFeatures);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceBufferDeviceAddressFeaturesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceCoherentMemoryFeaturesAMD);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceColorWriteEnableFeaturesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceComputeShaderDerivativesFeaturesNV);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceConditionalRenderingFeaturesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceConservativeRasterizationPropertiesEXT);
@@ -9838,6 +9873,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR);
INSTANTIATE_SERIALISE_TYPE(VkPipelineCacheCreateInfo);
INSTANTIATE_SERIALISE_TYPE(VkPipelineColorBlendStateCreateInfo);
INSTANTIATE_SERIALISE_TYPE(VkPipelineColorWriteCreateInfoEXT);
INSTANTIATE_SERIALISE_TYPE(VkPipelineCreationFeedbackCreateInfoEXT);
INSTANTIATE_SERIALISE_TYPE(VkPipelineDepthStencilStateCreateInfo);
INSTANTIATE_SERIALISE_TYPE(VkPipelineDiscardRectangleStateCreateInfoEXT);
+7
View File
@@ -181,6 +181,13 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd,
if(!scissors.empty() && dynamicStates[VkDynamicScissor])
ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), 0, (uint32_t)scissors.size(), &scissors[0]);
if(vk->DynamicColorWrite())
{
if(!colorWriteEnable.empty() && dynamicStates[VkDynamicColorWriteEXT])
ObjDisp(cmd)->CmdSetColorWriteEnableEXT(Unwrap(cmd), (uint32_t)colorWriteEnable.size(),
colorWriteEnable.data());
}
if(vk->ExtendedDynamicState())
{
if(!views.empty() && dynamicStates[VkDynamicViewportCountEXT])
+3
View File
@@ -191,6 +191,9 @@ struct VulkanRenderState
VkBool32 stencilTestEnable = VK_FALSE;
// color write enable
rdcarray<VkBool32> colorWriteEnable;
private:
ResourceId framebuffer;
rdcarray<ResourceId> fbattachments;
+2 -1
View File
@@ -28,7 +28,7 @@
template <>
rdcstr DoStringise(const VulkanChunk &el)
{
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1166, "Chunks changed without updating names");
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1167, "Chunks changed without updating names");
BEGIN_ENUM_STRINGISE(VulkanChunk)
{
@@ -198,6 +198,7 @@ rdcstr DoStringise(const VulkanChunk &el)
STRINGISE_ENUM_CLASS(vkCmdWriteTimestamp2KHR);
STRINGISE_ENUM_CLASS(vkQueueSubmit2KHR);
STRINGISE_ENUM_CLASS(vkCmdWriteBufferMarker2AMD);
STRINGISE_ENUM_CLASS(vkCmdSetColorWriteEnableEXT);
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
}
END_ENUM_STRINGISE()
@@ -36,7 +36,7 @@ static rdcstr ToHumanStr(const VkAttachmentLoadOp &el)
{
case VK_ATTACHMENT_LOAD_OP_LOAD: return "Load";
case VK_ATTACHMENT_LOAD_OP_CLEAR: return "Clear";
case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return "Don't Care";
case VK_ATTACHMENT_LOAD_OP_NONE_EXT: return "None";
}
END_ENUM_STRINGISE();
}
@@ -47,6 +47,7 @@ static rdcstr ToHumanStr(const VkAttachmentStoreOp &el)
{
case VK_ATTACHMENT_STORE_OP_STORE: return "Store";
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return "Don't Care";
case VK_ATTACHMENT_STORE_OP_NONE_EXT: return "None";
}
END_ENUM_STRINGISE();
}
@@ -1485,8 +1486,17 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman
if(att >= rpinfo.attachments.size())
continue;
if(rpinfo.attachments[att].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
rpinfo.attachments[att].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
VkImageAspectFlags clearAspects = 0;
// loadOp governs color, and depth
if(rpinfo.attachments[att].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
clearAspects |= VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
// stencilLoadOp governs the stencil
if(rpinfo.attachments[att].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
clearAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
// if any aspect is set to clear, go check it in more detail
if(clearAspects != 0)
{
VulkanCreationInfo::ImageView viewinfo = m_CreationInfo.m_ImageView[fbattachments[att]];
@@ -1498,8 +1508,15 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman
clear.clearValue = unwrappedInfo.pClearValues[att];
else
RDCWARN("Missing clear value for attachment %u", att);
clearrects.push_back(rect);
clearatts.push_back(clear);
// check that the actual aspects in the attachment overlap with those being cleared.
// In particular this means we ignore stencil load op being CLEAR for a color
// attachment - that doesn't mean we should clear the color
if(clear.aspectMask & clearAspects)
{
clearrects.push_back(rect);
clearatts.push_back(clear);
}
}
}
@@ -1662,7 +1679,8 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
if(renderArea_covers_entire_framebuffer && framebuffer_reference_entire_attachment)
{
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD)
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD &&
rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
{
refType = eFrameRef_CompleteWrite;
}
@@ -2291,7 +2309,8 @@ void WrappedVulkan::vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer,
if(renderArea_covers_entire_framebuffer && framebuffer_reference_entire_attachment)
{
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD)
if(rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_LOAD &&
rpInfo->loadOpTable[i] != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
{
refType = eFrameRef_CompleteWrite;
}
@@ -2758,6 +2777,12 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(SerialiserType &ser, VkCommandBu
renderstate.vbuffers[bind.vbufferBinding].stride = bind.bytestride;
}
}
if(!pipeInfo.dynamicStates[VkDynamicColorWriteEXT])
{
renderstate.colorWriteEnable.resize(pipeInfo.attachments.size());
for(size_t i = 0; i < renderstate.colorWriteEnable.size(); i++)
renderstate.colorWriteEnable[i] = pipeInfo.attachments[i].channelWriteMask != 0;
}
}
}
}
@@ -2799,6 +2799,15 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
CHECK_PHYS_EXT_FEATURE(globalPriorityQuery);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceColorWriteEnableFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(colorWriteEnable);
m_DynColorWrite = (ext->colorWriteEnable != VK_FALSE);
}
END_PHYS_EXT_CHECK();
}
if(availFeatures.depthClamp)
@@ -1514,6 +1514,72 @@ void WrappedVulkan::vkCmdSetStencilOpEXT(VkCommandBuffer commandBuffer, VkStenci
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdSetColorWriteEnableEXT(SerialiserType &ser,
VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkBool32 *pColorWriteEnables)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT(attachmentCount);
SERIALISE_ELEMENT_ARRAY(pColorWriteEnables, attachmentCount).Important();
Serialise_DebugMessages(ser);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer));
if(IsActiveReplaying(m_State))
{
if(InRerecordRange(m_LastCmdBufferID))
{
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
{
VulkanRenderState &renderstate = GetCmdRenderState();
renderstate.colorWriteEnable.assign(pColorWriteEnables, attachmentCount);
}
}
else
{
commandBuffer = VK_NULL_HANDLE;
}
}
if(commandBuffer != VK_NULL_HANDLE)
ObjDisp(commandBuffer)
->CmdSetColorWriteEnableEXT(Unwrap(commandBuffer), attachmentCount, pColorWriteEnables);
}
return true;
}
void WrappedVulkan::vkCmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkBool32 *pColorWriteEnables)
{
SCOPED_DBG_SINK();
SERIALISE_TIME_CALL(
ObjDisp(commandBuffer)
->CmdSetColorWriteEnableEXT(Unwrap(commandBuffer), attachmentCount, pColorWriteEnables));
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetColorWriteEnableEXT);
Serialise_vkCmdSetColorWriteEnableEXT(ser, commandBuffer, attachmentCount, pColorWriteEnables);
record->AddChunk(scope.Get(&record->cmdInfo->alloc));
}
}
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetViewport, VkCommandBuffer commandBuffer,
uint32_t firstViewport, uint32_t viewportCount,
const VkViewport *pViewports);
@@ -1587,3 +1653,6 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetStencilTestEnableEXT, VkCommandBuf
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetStencilOpEXT, VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp,
VkStencilOp depthFailOp, VkCompareOp compareOp);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdSetColorWriteEnableEXT, VkCommandBuffer commandBuffer,
uint32_t attachmentCount, const VkBool32 *pColorWriteEnables);
@@ -957,8 +957,10 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass(SerialiserType &ser, VkDevice d
{
if(m_ReplayOptions.optimisation != ReplayOptimisationLevel::Fastest)
{
att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT)
att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].stencilStoreOp != VK_ATTACHMENT_STORE_OP_NONE_EXT)
att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
{
@@ -1035,8 +1037,10 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass(SerialiserType &ser, VkDevice d
// without doing a clear or a DONT_CARE load.
for(uint32_t i = 0; i < CreateInfo.attachmentCount; i++)
{
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(att[i].loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(att[i].stencilLoadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
VkRenderPassCreateInfo loadInfo = CreateInfo;
@@ -1139,8 +1143,10 @@ VkResult WrappedVulkan::vkCreateRenderPass(VkDevice device, const VkRenderPassCr
for(uint32_t i = 0; i < info.attachmentCount; i++)
{
atts[i] = info.pAttachments[i];
atts[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
atts[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(atts[i].loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
atts[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(atts[i].stencilLoadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
atts[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
info.pAttachments = atts.data();
@@ -1207,8 +1213,10 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass2(SerialiserType &ser, VkDevice
VkAttachmentDescription2 *att = (VkAttachmentDescription2 *)CreateInfo.pAttachments;
for(uint32_t i = 0; i < CreateInfo.attachmentCount; i++)
{
att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].storeOp != VK_ATTACHMENT_STORE_OP_NONE_EXT)
att[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].stencilStoreOp != VK_ATTACHMENT_STORE_OP_NONE_EXT)
att[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
if(att[i].loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -1265,8 +1273,10 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass2(SerialiserType &ser, VkDevice
// without doing a clear or a DONT_CARE load.
for(uint32_t i = 0; i < CreateInfo.attachmentCount; i++)
{
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(att[i].loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
att[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(att[i].stencilLoadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
att[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
VkRenderPassCreateInfo2 loadInfo = CreateInfo;
@@ -1371,8 +1381,10 @@ VkResult WrappedVulkan::vkCreateRenderPass2(VkDevice device,
for(uint32_t i = 0; i < info.attachmentCount; i++)
{
atts[i] = info.pAttachments[i];
atts[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
atts[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(atts[i].loadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
atts[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
if(atts[i].stencilLoadOp != VK_ATTACHMENT_LOAD_OP_NONE_EXT)
atts[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
}
info.pAttachments = atts.data();
+1
View File
@@ -29,6 +29,7 @@ set(VULKAN_SRC
vk/vk_large_descriptor_sets.cpp
vk/vk_leak_check.cpp
vk/vk_line_raster.cpp
vk/vk_load_store_none.cpp
vk/vk_mesh_zoo.cpp
vk/vk_misaligned_dirty.cpp
vk/vk_multi_thread_windows.cpp
+1
View File
@@ -290,6 +290,7 @@
<ClCompile Include="vk\vk_large_buffer.cpp" />
<ClCompile Include="vk\vk_large_descriptor_sets.cpp" />
<ClCompile Include="vk\vk_leak_check.cpp" />
<ClCompile Include="vk\vk_load_store_none.cpp" />
<ClCompile Include="vk\vk_mesh_zoo.cpp" />
<ClCompile Include="vk\vk_parameter_zoo.cpp" />
<ClCompile Include="vk\vk_imageless_framebuffer.cpp" />
+3
View File
@@ -607,6 +607,9 @@
<ClCompile Include="d3d12\d3d12_descriptor_indexing.cpp">
<Filter>D3D12\demos</Filter>
</ClCompile>
<ClCompile Include="vk\vk_load_store_none.cpp">
<Filter>Vulkan\demos</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D11">
+268
View File
@@ -0,0 +1,268 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2021 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "vk_test.h"
RD_TEST(VK_Load_Store_None, VulkanGraphicsTest)
{
static constexpr const char *Description =
"Tests the use of LOAD_OP_NONE and STORE_OP_NONE to preserve an attachment without "
"modification.";
std::string pixel = R"EOSHADER(
#version 460 core
layout(location = 0, index = 0) out vec4 Color1;
layout(location = 1, index = 0) out vec4 Color2;
void main()
{
Color1 = Color2 = vec4(1.0, 0.0, 0.0, 1.0);
}
)EOSHADER";
void Prepare(int argc, char **argv)
{
devExts.push_back(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME);
// require dynamic color write enable for the easiest time testing both load and store op none.
//
// these ops are there because renderpasses with different ops but everything else is the same
// are still compatible, so these can be switched last minute without needing to recompile a
// pipeline. So the cases they are useful are those where a pipeline is declared to use an
// attachment then at the last minute the application realises it doesn't need it.
//
// NONE store op can be useful on its own in a couple of scenarios when you're using read-only
// depth, as there's no way to express "this was not written and no synchronisation is needed"
// because don't care and store are both write operations.
//
// NONE load op is only useful when you want to preserve an attachment that's now unused but had
// it declared as modified and e.g. load/store'd at creation time. For depth this could happen
// with EXT_extended_dynamic_state if you disabled depth testing which was previously used,
// and wanted to preserve the depth. That's more annoying to test though, so we require
// color_write_enable for the same purpose (dynamically disabling).
//
// We could just create the pipeline as not writing to those attachments from the start, but
// that would be a bit too artificial and not how this is used in practice.
devExts.push_back(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
VulkanGraphicsTest::Prepare(argc, argv);
static VkPhysicalDeviceColorWriteEnableFeaturesEXT colorEnableFeats = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT,
};
colorEnableFeats.colorWriteEnable = VK_TRUE;
devInfoNext = &colorEnableFeats;
}
int main()
{
// initialise, create window, create context, etc
if(!Init())
return 3;
VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo({}));
AllocatedImage img(
this,
vkh::ImageCreateInfo(mainWindow->scissor.extent.width, mainWindow->scissor.extent.height, 0,
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
VkImageView imgview = createImageView(
vkh::ImageViewCreateInfo(img.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32G32B32A32_SFLOAT));
AllocatedImage preserveimg(
this,
vkh::ImageCreateInfo(mainWindow->scissor.extent.width, mainWindow->scissor.extent.height, 0,
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
setName(preserveimg.image, "PreserveImg");
VkImageView preserveimgview = createImageView(vkh::ImageViewCreateInfo(
preserveimg.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R32G32B32A32_SFLOAT));
vkh::RenderPassCreator renderPassCreateInfo;
renderPassCreateInfo.attachments.push_back(
vkh::AttachmentDescription(VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, VK_ATTACHMENT_LOAD_OP_CLEAR));
// unused attachment
renderPassCreateInfo.attachments.push_back(vkh::AttachmentDescription(
VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE));
renderPassCreateInfo.addSubpass({VkAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL}),
VkAttachmentReference({1, VK_IMAGE_LAYOUT_GENERAL})});
// this RP has clear/store
VkRenderPass pipeRP = createRenderPass(renderPassCreateInfo);
renderPassCreateInfo.attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_NONE_EXT;
renderPassCreateInfo.attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_NONE_EXT;
// this RP has none/none and will be used for rendering
VkRenderPass renderPass = createRenderPass(renderPassCreateInfo);
VkFramebuffer framebuffer = createFramebuffer(vkh::FramebufferCreateInfo(
renderPass, {imgview, preserveimgview}, mainWindow->scissor.extent));
vkh::GraphicsPipelineCreateInfo pipeCreateInfo;
pipeCreateInfo.layout = layout;
pipeCreateInfo.renderPass = pipeRP;
pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
vkh::vertexAttr(0, 0, DefaultA2V, pos), vkh::vertexAttr(1, 0, DefaultA2V, col),
vkh::vertexAttr(2, 0, DefaultA2V, uv),
};
pipeCreateInfo.stages = {
CompileShaderModule(VKDefaultVertex, ShaderLang::glsl, ShaderStage::vert, "main"),
CompileShaderModule(pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
};
pipeCreateInfo.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
pipeCreateInfo.colorBlendState.attachments.push_back({
// blendEnable
VK_FALSE,
// color*
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD,
// alpha*
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD,
// colorWriteMask
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT,
});
VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);
AllocatedBuffer vb(
this, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
vb.upload(DefaultTri);
{
VkCommandBuffer cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
// put the attachment in GENERAL
vkh::cmdPipelineBarrier(
cmd, {
vkh::ImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
preserveimg.image),
});
// use the original pipeline's RP to clear and store
vkCmdBeginRenderPass(cmd, vkh::RenderPassBeginInfo(pipeRP, framebuffer, mainWindow->scissor,
{vkh::ClearValue(0.2f, 0.2f, 0.2f, 1.0f),
vkh::ClearValue(0.2f, 0.2f, 0.2f, 1.0f)}),
VK_SUBPASS_CONTENTS_INLINE);
// clear a rect in the middle of the preserve attachment to green
VkClearAttachment att = {};
att.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
att.clearValue.color.float32[1] = 1.0f;
att.clearValue.color.float32[3] = 1.0f;
att.colorAttachment = 1;
VkClearRect rect = {};
rect.baseArrayLayer = 0;
rect.layerCount = 1;
rect.rect.offset.x = 150;
rect.rect.offset.y = 100;
rect.rect.extent.width = 75;
rect.rect.extent.height = 50;
vkCmdClearAttachments(cmd, 1, &att, 1, &rect);
vkCmdEndRenderPass(cmd);
// we'll be reading later, synchronise here once
vkh::cmdPipelineBarrier(
cmd, {
vkh::ImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_GENERAL, preserveimg.image),
});
vkEndCommandBuffer(cmd);
Submit(99, 99, {cmd});
}
while(Running())
{
VkCommandBuffer cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
VkImage swapimg =
StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
vkCmdBeginRenderPass(cmd, vkh::RenderPassBeginInfo(renderPass, framebuffer, mainWindow->scissor,
{vkh::ClearValue(0.2f, 0.2f, 0.2f, 1.0f),
vkh::ClearValue(1.0f, 0.2f, 0.2f, 1.0f)}),
VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vkCmdSetViewport(cmd, 0, 1, &mainWindow->viewport);
vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
VkBool32 enables[2] = {true, false};
vkCmdSetColorWriteEnableEXT(cmd, 2, enables);
vkCmdDraw(cmd, 3, 1, 0, 0);
vkCmdEndRenderPass(cmd);
// no need to synchronise here, nothing changed the preserved image
blitToSwap(cmd, preserveimg.image, VK_IMAGE_LAYOUT_GENERAL, swapimg, VK_IMAGE_LAYOUT_GENERAL);
FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
vkEndCommandBuffer(cmd);
Submit(0, 1, {cmd});
Present();
}
return 0;
}
};
REGISTER_TEST();
@@ -0,0 +1,21 @@
import renderdoc as rd
import rdtest
class VK_Load_Store_None(rdtest.TestCase):
demos_test_name = 'VK_Load_Store_None'
def check_capture(self):
res = self.get_resource_by_name('PreserveImg').resourceId
for action in [self.find_action("BeginRender"), self.find_action("Draw"), self.find_action("EndRender"),
self.find_action("Blit")]:
self.controller.SetFrameEvent(action.eventId, True)
self.check_pixel_value(res, 200, 125, [0.0, 1.0, 0.0, 1.0])
self.check_pixel_value(res, 200, 90, [0.2, 0.2, 0.2, 1.0])
self.check_pixel_value(res, 200, 160, [0.2, 0.2, 0.2, 1.0])
self.check_pixel_value(res, 250, 125, [0.2, 0.2, 0.2, 1.0])
self.check_pixel_value(res, 100, 125, [0.2, 0.2, 0.2, 1.0])
rdtest.log.success("Preserved image is as expected at {}".format(self.action_name(action)))