Repository: KhronosGroup/Vulkan-ValidationLayers
Pull request #9612: layers: Better ShaderInputNotProduced error message
Author: login: spencer-lunarg
Created: 2025-03-06T23:59:55Z | Merged: 2025-03-07T15:24:50Z

new message

```
Validation Warning: [ Undefined-Value-ShaderInputNotProduced-DynamicRendering ] | MessageID = 0x733b5ff8
vkCmdDrawIndexed(): Inside the fragment shader, the output Locaiton 1 was never written to. This means the bound VkRenderingInfo::pColorAttachments[1].imageView (VkImageView 0x3a6cbb0000000025) will have undefined values written to it. The pipeline was created with pColorBlendState->pAttachments[1].colorWriteMask set to 0xf so setting it to zero is one way to prevent undefined values overriding your color attachment (this will require independentBlend, which is basically supported everywhere, to have some attachment have different colorWriteMask).
Spec information at https://docs.vulkan.org/spec/latest/chapters/interfaces.html#interfaces-fragmentoutput
Objects: 2
    [0] VkCommandBuffer 0x644d8413f0e0
    [1] VkPipeline 0xc25f26000000009c
```


Diff:
diff --git a/docs/debug_printf.md b/docs/debug_printf.md
index 92c3f9e5c85..ed91a8d2bc5 100644
--- a/docs/debug_printf.md
+++ b/docs/debug_printf.md
@@ -18,9 +18,9 @@ inspect and debug with them in RenderDoc, using vkconfig, or with environment va
 
 ## Turning on Debug Printf in Validation Layer
 
-We suggest to use Vulkan Configurator (`VkConfig`) to enable DebugPrintf
+We suggest to use Vulkan Configurator (`VkConfig`) to enable Debug Printf
 
-For those who "just need to quick use it" there is a `VK_LAYER_PRINTF_ONLY_PRESET` environment variable that will turn on DebugPrintf and turn off all of the other validation logic.
+For those who "just need to quick use it" there is a `VK_LAYER_PRINTF_ONLY_PRESET` environment variable that will turn on Debug Printf and turn off all of the other validation logic.
 
 ```bash
 # Windows
@@ -35,11 +35,11 @@ adb setprop debug.vulkan.khronos_validation.printf_only_preset=1
 
 ## Settings
 
-The following are the various DebugPrintf settings (listed as environment variables, but work like all other settings).
+The following are the various Debug Printf settings (listed as environment variables, but work like all other settings).
 
 > All settings also found in `VkConfig`
 
-- `VK_LAYER_PRINTF_ENABLE` will turn on DebugPrintf alongside the other validation
+- `VK_LAYER_PRINTF_ENABLE` will turn on Debug Printf alongside the other validation
     - `VK_LAYER_PRINTF_ENABLE=1` turn on
 - `VK_LAYER_PRINTF_TO_STDOUT` will print to `stdout` **instead** of the normal Debug Callback
     - `VK_LAYER_PRINTF_TO_STDOUT=1` turn on
@@ -65,11 +65,11 @@ void main() {
 }
 ```
 
-`glslang` will automatically add the DebugPrintf instructions
+`glslang` will automatically add the Debug Printf instructions
 
 ## Using Debug Printf in HLSL and Slang Shaders
 
-In HLSL and Slang, debug printf can be invoked as follows ([Try Online](https://godbolt.org/z/3ThznsdK8)):
+In HLSL and Slang, Debug Printf can be invoked as follows ([Try Online](https://godbolt.org/z/3ThznsdK8)):
 
 ```glsl
 void main() {
@@ -78,7 +78,7 @@ void main() {
 }
 ```
 
-Both `dxc` and `slangc` will automatically add the DebugPrintf instructions
+Both `dxc` and `slangc` will automatically add the Debug Printf instructions
 
 ## Recommendations
 
@@ -104,15 +104,15 @@ if (gl_LocalInvocationIndex == 0) {
 
 ## Debug Printf Output
 
-DebugPrintf error message are returned as `VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT`
+Debug Printf error message are returned as `VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT`
 
 For your custom callback, you can look for `0x4fe1fef9` in `VkDebugUtilsMessengerCallbackDataEXT::messageIdNumber` as the magic hash if it is a Debug Printf message
 
-The Validation Layers will try and turn on `info` level messages when using DebugPrintf so the message is found
+The Validation Layers will try to turn on `info` level messages when using Debug Printf so the message is found
 
 The `VkDebugUtilsMessengerCallbackDataEXT::pMessage` will contain the location and on a newline print out the error message such as:
 
-> vkQueueSubmit(): pSubmits[0] DebugPrintf:
+> vkQueueSubmit(): pSubmits[0] Debug Printf:
 >
 > x == 100
 
@@ -174,7 +174,7 @@ The vkCmdDrawIndexed in question now has 51 messages.
 Normally, developers will use a high-level language like HLSL or GLSL to generate SPIR-V.
 However, in some cases, developers may wish to insert Debug Printfs directly into SPIR-V
 
-To execute debug printfs in a SPIR-V shader, a developer will need the following two
+To execute Debug Printf in a SPIR-V shader, a developer will need the following two
 instructions specified:
 
 ```
@@ -182,14 +182,14 @@ OpExtension "SPV_KHR_non_semantic_info"
 %N0 = OpExtInstImport NonSemantic.DebugPrintf
 ```
 
-Debug printf operations can then be specified in any function with the following instruction:
+Debug Printf operations can then be specified in any function with the following instruction:
 `%NN = OpExtInst %void %N0 1 %N1 %N2 %N3` ...
 where:
-* `N0` is the result id of the OpExtInstImport NonSemantic.DebugPrintf
-* `1` is the opcode of the DebugPrintf instruction in NonSemantic.DebugPrintf
-* `N1` is the result of an OpString containing the format for the debug printf
+* `N0` is the result id of the `OpExtInstImport NonSemantic.DebugPrintf`
+* `1` is the opcode of the Debug Printf instruction in `NonSemantic.DebugPrintf`
+* `N1` is the result of an OpString containing the format for the Debug Printf
 * `N2`, `N3`, ... are result ids of scalar and vector values to be printed
-* `NN` is the result id of the debug printf operation. This value is undefined.
+* `NN` is the result id of the Debug Printf operation. This value is undefined.
 
 > `OpExtInstImport` of any `NonSemantic*` is properly supported with the `VK_KHR_shader_non_semantic_info` device extension. Some older compiler stacks might not handle these unknown instructions well, some will ignore it as desired.
 
diff --git a/layers/core_checks/cc_shader_interface.cpp b/layers/core_checks/cc_shader_interface.cpp
index eea9b1572ee..a3a90bd0970 100644
--- a/layers/core_checks/cc_shader_interface.cpp
+++ b/layers/core_checks/cc_shader_interface.cpp
@@ -516,16 +516,8 @@ bool CoreChecks::ValidateFsOutputsAgainstRenderPass(const spirv::Module &module_
         const VkAttachmentDescription2 *attachment = attachment_info.attachment;
         const spirv::StageInterfaceVariable *output = attachment_info.output;
         if (attachment && !output) {
-            const auto &attachment_states = pipeline.AttachmentStates();
-            if (location < attachment_states.size() && attachment_states[location].colorWriteMask != 0) {
-                skip |= LogUndefinedValue(
-                    "Undefined-Value-ShaderInputNotProduced", module_state.handle(), create_info_loc,
-                    "Inside the fragment shader, the output Locaiton %" PRIu32
-                    " was never written to. This means anything future VkSubpassDescription::pColorAttachments[%" PRIu32
-                    "] will have undefined values written to it.\nSpec information at "
-                    "https://docs.vulkan.org/spec/latest/chapters/interfaces.html#interfaces-fragmentoutput",
-                    location, location);
-            }
+            // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+            // Need to understand when undefined or not
         } else if (!attachment && output) {
             // With alphaToCoverage, the write is not "discarded" as the alpha mask is still updated
             if (!alpha_to_coverage_enabled || location != 0) {
@@ -576,7 +568,8 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
     };
     std::map<uint32_t, Attachment> location_map;
 
-    for (uint32_t i = 0; i < rp_state.dynamic_rendering_begin_rendering_info.colorAttachmentCount; ++i) {
+    const uint32_t color_attachment_count = rp_state.dynamic_rendering_begin_rendering_info.colorAttachmentCount;
+    for (uint32_t i = 0; i < color_attachment_count; ++i) {
         location_map[i].rendering_attachment_info = rp_state.dynamic_rendering_begin_rendering_info.pColorAttachments[i].ptr();
     }
 
@@ -602,18 +595,8 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
         const spirv::StageInterfaceVariable *output = attachment_info.output;
 
         if (has_attachment && !output) {
-            const auto image_view_state = Get<vvl::ImageView>(attachment_info.rendering_attachment_info->imageView);
-            const VkColorComponentFlags color_write_mask = last_bound_state.GetColorWriteMask(location);
-            if (color_write_mask != 0) {
-                const LogObjectList objlist = last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS);
-                skip |= LogUndefinedValue("Undefined-Value-ShaderInputNotProduced-DynamicRendering", objlist, loc,
-                                          "Inside the fragment shader, the output Locaiton %" PRIu32
-                                          " was never written to. This means the bound VkRenderingInfo::pColorAttachments[%" PRIu32
-                                          "].imageView (%s) will have undefined values written to it.\nSpec information at "
-                                          "https://docs.vulkan.org/spec/latest/chapters/interfaces.html#interfaces-fragmentoutput",
-                                          location, location,
-                                          FormatHandle(attachment_info.rendering_attachment_info->imageView).c_str());
-            }
+            // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+            // Need to understand when undefined or not
         } else if (!has_attachment && output) {
             // With alphaToCoverage, the write is not "discarded" as the alpha mask is still updated
             if (!last_bound_state.IsAlphaToCoverage() || location != 0) {
diff --git a/layers/drawdispatch/descriptor_validator.cpp b/layers/drawdispatch/descriptor_validator.cpp
index a19b2138c12..c821092fc44 100644
--- a/layers/drawdispatch/descriptor_validator.cpp
+++ b/layers/drawdispatch/descriptor_validator.cpp
@@ -402,12 +402,24 @@ bool DescriptorValidator::ValidateDescriptor(const spirv::ResourceInterfaceVaria
                 << string_SpirvImageFormat(resource_variable.info.image_format) << " (equivalent to "
                 << string_VkFormat(resource_variable.info.image_format) << ") which doesn't match the "
                 << dev_state.FormatHandle(image_view) << " format (" << string_VkFormat(image_view_ci.format)
-                << "). Any loads or stores with the variable will produce undefined values.";
+                << "). Any loads or stores with the variable will produce undefined values to the whole imamge (not just the texel "
+                   "being accessed).";
             if (vkuFormatCompatibilityClass(image_view_ci.format) ==
                 vkuFormatCompatibilityClass(resource_variable.info.image_format)) {
-                msg << " While the formats are compatible, Storage Images must exactly match. Two ways to resolve this are\n";
-                msg << "1. Set your ImageView to " << string_VkFormat(resource_variable.info.image_format)
-                    << " and swizzle the values in the shader to match the desired results.\n";
+                msg << " While the formats are compatible, Storage Images must exactly match. Few ways to resolve this are\n";
+                if (vkuFormatComponentCount(image_view_ci.format) == vkuFormatComponentCount(resource_variable.info.image_format)) {
+                    msg << "1. Set your ImageView to " << string_VkFormat(resource_variable.info.image_format)
+                        << " and swizzle the values in the shader to match the desired results.\n";
+                } else {
+                    const char *suggested_format = string_SpirvImageFormat(image_view_ci.format);
+                    if (strncmp(suggested_format, "Unknown", 7) != 0) {
+                        msg << "1. Change your shader to use " << suggested_format << " instead as that matches "
+                            << string_VkFormat(image_view_ci.format) << "\n";
+                    } else {
+                        msg << "1. Find an SPIR-V Image format that can be mapped to a desired VkImageView format "
+                               "https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#spirvenv-image-formats\n";
+                    }
+                }
                 msg << "2. Use the Unknown format in your shader (will need the widely supported "
                        "shaderStorageImageWriteWithoutFormat feature)";
             }
@@ -968,11 +980,23 @@ bool DescriptorValidator::ValidateDescriptor(const spirv::ResourceInterfaceVaria
             << string_SpirvImageFormat(resource_variable.info.image_format) << " (equivalent to "
             << string_VkFormat(resource_variable.info.image_format) << ") which doesn't match the "
             << dev_state.FormatHandle(buffer_view) << " format (" << string_VkFormat(buffer_view_format)
-            << "). Any loads or stores with the variable will produce undefined values.";
+            << ").Any loads or stores with the variable will produce undefined values to the whole imamge (not just the texel "
+               "being accessed).";
         if (vkuFormatCompatibilityClass(buffer_view_format) == vkuFormatCompatibilityClass(resource_variable.info.image_format)) {
-            msg << " While the formats are compatible, Texel Buffers must exactly match. Two ways to resolve this are\n";
-            msg << "1. Set your ImageView to " << string_VkFormat(resource_variable.info.image_format)
-                << " and swizzle the values in the shader to match the desired results.\n";
+            msg << " While the formats are compatible, Texel Buffers must exactly match. Few ways to resolve this are\n";
+            if (vkuFormatComponentCount(buffer_view_format) == vkuFormatComponentCount(resource_variable.info.image_format)) {
+                msg << "1. Set your BuffereView to " << string_VkFormat(resource_variable.info.image_format)
+                    << " and swizzle the values in the shader to match the desired results.\n";
+            } else {
+                const char *suggested_format = string_SpirvImageFormat(buffer_view_format);
+                if (strncmp(suggested_format, "Unknown", 7) != 0) {
+                    msg << "1. Change your shader to use " << suggested_format << " instead as that matches "
+                        << string_VkFormat(buffer_view_format) << "\n";
+                } else {
+                    msg << "1. Find an SPIR-V Image format that can be mapped to a desired VkBuffereView format "
+                           "https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#spirvenv-image-formats\n";
+                }
+            }
             msg << "2. Use the Unknown format in your shader";
         }
         msg << "\nSpec information at https://docs.vulkan.org/spec/latest/chapters/textures.html#textures-format-validation";
diff --git a/tests/unit/shader_interface.cpp b/tests/unit/shader_interface.cpp
index a53e5bf7aeb..80bc3ed9ac3 100644
--- a/tests/unit/shader_interface.cpp
+++ b/tests/unit/shader_interface.cpp
@@ -1665,7 +1665,8 @@ TEST_F(NegativeShaderInterface, PackingInsideArray) {
     CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-RuntimeSpirv-OpEntryPoint-08743");
 }
 
-TEST_F(NegativeShaderInterface, FragmentOutputNotWritten) {
+// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+TEST_F(NegativeShaderInterface, DISABLED_FragmentOutputNotWritten) {
     TEST_DESCRIPTION(
         "Test that an error is produced for a fragment shader which does not provide an output for one of the pipeline's color "
         "attachments");
@@ -1679,12 +1680,13 @@ TEST_F(NegativeShaderInterface, FragmentOutputNotWritten) {
     CreatePipelineHelper pipe(*this);
     pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
     pipe.cb_attachments_.colorWriteMask = 0xf;  // all components
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced");
     pipe.CreateGraphicsPipeline();
     m_errorMonitor->VerifyFound();
 }
 
-TEST_F(NegativeShaderInterface, FragmentOutputNotWrittenDynamicRendering) {
+// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+TEST_F(NegativeShaderInterface, DISABLED_FragmentOutputNotWrittenDynamicRendering) {
     AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
     AddRequiredFeature(vkt::Feature::dynamicRendering);
     RETURN_IF_SKIP(Init());
@@ -1706,14 +1708,15 @@ TEST_F(NegativeShaderInterface, FragmentOutputNotWrittenDynamicRendering) {
     m_command_buffer.Begin();
     m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
     vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced-DynamicRendering");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced-DynamicRendering");
     vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0);
     m_errorMonitor->VerifyFound();
     m_command_buffer.EndRendering();
     m_command_buffer.End();
 }
 
-TEST_F(NegativeShaderInterface, FragmentOutputNotWrittenDynamicRenderingShaderObject) {
+// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+TEST_F(NegativeShaderInterface, DISABLED_FragmentOutputNotWrittenDynamicRenderingShaderObject) {
     AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
     AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
     AddRequiredFeature(vkt::Feature::dynamicRendering);
@@ -1731,7 +1734,7 @@ TEST_F(NegativeShaderInterface, FragmentOutputNotWrittenDynamicRenderingShaderOb
     m_command_buffer.BindShaders(vert_shader, frag_shader);
     VkColorComponentFlags color_write_mask = 0xf;  // all
     vk::CmdSetColorWriteMaskEXT(m_command_buffer.handle(), 0, 1, &color_write_mask);
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced-DynamicRendering");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced-DynamicRendering");
     vk::CmdDraw(m_command_buffer.handle(), 4, 1, 0, 0);
     m_errorMonitor->VerifyFound();
     m_command_buffer.EndRendering();
@@ -1774,7 +1777,7 @@ TEST_F(NegativeShaderInterface, DISABLED_FragmentOutputNotWrittenArray) {
     pipe.cb_ci_.attachmentCount = 2;
     pipe.cb_ci_.pAttachments = color_blends;
     pipe.gp_ci_.renderPass = rp.Handle();
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced");
     pipe.CreateGraphicsPipeline();
     m_errorMonitor->VerifyFound();
 }
@@ -1827,7 +1830,7 @@ TEST_F(NegativeShaderInterface, DISABLED_FragmentOutputNotWrittenArrayDynamicRen
     m_command_buffer.Begin();
     m_command_buffer.BeginRendering(rendering_info);
     vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced-DynamicRendering");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced-DynamicRendering");
     vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0);
     m_errorMonitor->VerifyFound();
     m_command_buffer.EndRendering();
@@ -2178,7 +2181,8 @@ TEST_F(NegativeShaderInterface, DISABLED_PhysicalStorageBuffer) {
     m_errorMonitor->VerifyFound();
 }
 
-TEST_F(NegativeShaderInterface, MultipleFragmentAttachment) {
+// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+TEST_F(NegativeShaderInterface, DISABLED_MultipleFragmentAttachment) {
     TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7923");
     RETURN_IF_SKIP(Init());
 
@@ -2221,12 +2225,13 @@ TEST_F(NegativeShaderInterface, MultipleFragmentAttachment) {
     pipe.cb_ci_.attachmentCount = 3;
     pipe.cb_ci_.pAttachments = color_blends;
     pipe.gp_ci_.renderPass = rp.Handle();
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced");
     pipe.CreateGraphicsPipeline();
     m_errorMonitor->VerifyFound();
 }
 
-TEST_F(NegativeShaderInterface, MultipleFragmentAttachmentDynamicRendering) {
+// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9616
+TEST_F(NegativeShaderInterface, DISABLED_MultipleFragmentAttachmentDynamicRendering) {
     AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
     AddRequiredFeature(vkt::Feature::dynamicRendering);
     RETURN_IF_SKIP(Init());
@@ -2278,7 +2283,7 @@ TEST_F(NegativeShaderInterface, MultipleFragmentAttachmentDynamicRendering) {
     m_command_buffer.Begin();
     m_command_buffer.BeginRendering(rendering_info);
     vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
-    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderInputNotProduced-DynamicRendering");
+    m_errorMonitor->SetDesiredWarning("Undefined-Value-ShaderOutputNotProduced-DynamicRendering");
     vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0);
     m_errorMonitor->VerifyFound();
     m_command_buffer.EndRendering();
diff --git a/tests/unit/shader_storage_image.cpp b/tests/unit/shader_storage_image.cpp
index 6e2def8bd39..caba8094738 100644
--- a/tests/unit/shader_storage_image.cpp
+++ b/tests/unit/shader_storage_image.cpp
@@ -928,3 +928,5 @@ TEST_F(NegativeShaderStorageImage, FormatComponentWidthMismatch) {
 }
 
 TEST_F(NegativeShaderStorageImage, FormatCompatibleMismatch) { FormatComponentMismatchTest("Rgba8", VK_FORMAT_B8G8R8A8_UNORM); }
+
+TEST_F(NegativeShaderStorageImage, FormatCompatibleNonSwizzle) { FormatComponentMismatchTest("R32f", VK_FORMAT_R16G16_UNORM); }


Reviews:
user: login: arno-lunarg
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T09:24:32Z
user: login: spencer-lunarg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T13:52:13Z
user: login: spencer-lunarg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T13:52:56Z

Review comments:
diff_hunk: @@ -605,14 +606,29 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
             const auto image_view_state = Get<vvl::ImageView>(attachment_info.rendering_attachment_info->imageView);
             const VkColorComponentFlags color_write_mask = last_bound_state.GetColorWriteMask(location);
             if (color_write_mask != 0) {
+                std::ostringstream msg;
+                msg << "Inside the fragment shader, the output Locaiton " << location
path: layers/core_checks/cc_shader_interface.cpp
user: login: arno-lunarg
body: ```suggestion
                msg << "Inside the fragment shader, the output Location" << location
```
created_at: 2025-03-07T09:22:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -605,14 +606,29 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
             const auto image_view_state = Get<vvl::ImageView>(attachment_info.rendering_attachment_info->imageView);
             const VkColorComponentFlags color_write_mask = last_bound_state.GetColorWriteMask(location);
             if (color_write_mask != 0) {
+                std::ostringstream msg;
+                msg << "Inside the fragment shader, the output Locaiton " << location
+                    << " was never written to. This means the bound VkRenderingInfo::pColorAttachments[" << location
+                    << "].imageView (" << FormatHandle(attachment_info.rendering_attachment_info->imageView)
+                    << ") will have undefined values written to it. ";
+                if (last_bound_state.pipeline_state) {
+                    msg << "The pipeline was created with pColorBlendState->pAttachments[" << location
+                        << "].colorWriteMask set to ";
+                } else {
+                    msg << "The last call to vkCmdSetColorWriteMaskEXT for attachment " << location
+                        << " set the colorWriteMask to ";
+                }
+                msg << "0x" << std::hex << (uint32_t)color_write_mask
+                    << " so setting it to zero is one way to prevent undefined values overriding your color attachment";
+                if (color_attachment_count > 1) {
+                    msg << " (this will require independentBlend, which is basically supported everywhere, to have some attachment "
path: layers/core_checks/cc_shader_interface.cpp
user: login: arno-lunarg
body: ```suggestion
                    msg << " (this will require independentBlend, which is basically supported everywhere, to have some attachments "
```
(not sure?)
created_at: 2025-03-07T09:23:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -605,14 +606,29 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
             const auto image_view_state = Get<vvl::ImageView>(attachment_info.rendering_attachment_info->imageView);
             const VkColorComponentFlags color_write_mask = last_bound_state.GetColorWriteMask(location);
             if (color_write_mask != 0) {
+                std::ostringstream msg;
+                msg << "Inside the fragment shader, the output Locaiton " << location
path: layers/core_checks/cc_shader_interface.cpp
user: login: spencer-lunarg
body: no, I want it to say `Location 3` not `Location3`
created_at: 2025-03-07T13:52:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -605,14 +606,29 @@ bool CoreChecks::ValidateDrawDynamicRenderingFsOutputs(const LastBound &last_bou
             const auto image_view_state = Get<vvl::ImageView>(attachment_info.rendering_attachment_info->imageView);
             const VkColorComponentFlags color_write_mask = last_bound_state.GetColorWriteMask(location);
             if (color_write_mask != 0) {
+                std::ostringstream msg;
+                msg << "Inside the fragment shader, the output Locaiton " << location
+                    << " was never written to. This means the bound VkRenderingInfo::pColorAttachments[" << location
+                    << "].imageView (" << FormatHandle(attachment_info.rendering_attachment_info->imageView)
+                    << ") will have undefined values written to it. ";
+                if (last_bound_state.pipeline_state) {
+                    msg << "The pipeline was created with pColorBlendState->pAttachments[" << location
+                        << "].colorWriteMask set to ";
+                } else {
+                    msg << "The last call to vkCmdSetColorWriteMaskEXT for attachment " << location
+                        << " set the colorWriteMask to ";
+                }
+                msg << "0x" << std::hex << (uint32_t)color_write_mask
+                    << " so setting it to zero is one way to prevent undefined values overriding your color attachment";
+                if (color_attachment_count > 1) {
+                    msg << " (this will require independentBlend, which is basically supported everywhere, to have some attachment "
path: layers/core_checks/cc_shader_interface.cpp
user: login: spencer-lunarg
body: will fix
created_at: 2025-03-07T13:52:56Z
author_association: CONTRIBUTOR

PR comments:
user: login: ci-tester-lunarg
created_at: 2025-03-06T23:59:59Z
body: CI Vulkan-ValidationLayers build queued with queue ID 389115.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T00:05:02Z
body: CI Vulkan-ValidationLayers build # 19295 running.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T00:41:02Z
body: CI Vulkan-ValidationLayers build # 19295 passed.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T14:33:36Z
body: CI Vulkan-ValidationLayers build queued with queue ID 389430.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T14:34:22Z
body: CI Vulkan-ValidationLayers build queued with queue ID 389445.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T14:35:02Z
body: CI Vulkan-ValidationLayers build # 19297 running.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T14:53:35Z
body: CI Vulkan-ValidationLayers build queued with queue ID 389478.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T14:55:06Z
body: CI Vulkan-ValidationLayers build # 19298 running.
author_association: COLLABORATOR
user: login: ci-tester-lunarg
created_at: 2025-03-07T15:23:42Z
body: CI Vulkan-ValidationLayers build # 19298 passed.
author_association: COLLABORATOR