Reintroduce "VkDebug: Update macros to address issues in b/127433389"

36411219f had preprocessor issues on Windows.
This should now work on all platforms.

I had to change UNIMPLEMENTED() and UNREACHABLE() to always take a
format parameter to make this work on MSVC. This doesn't seem like
a terrible thing though - especially if we can incorporate the
frequency of hit UNIMPLEMENTED()'s to steer our focus.

Change-Id: Idc58dbe6caa3fb51e085c3b236904c640091deec
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27468
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index 28ded9a..06f9a66 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -161,7 +161,7 @@
 			return false;
 		}
 
-		VkImageSubresourceLayers subresLayers = 
+		VkImageSubresourceLayers subresLayers =
 		{
 			subresourceRange.aspectMask,
 			subresourceRange.baseMipLevel,
@@ -341,14 +341,14 @@
 		case VK_FORMAT_R32_SFLOAT:
 			c.x = *Pointer<Float>(element);
 			break;
-		case VK_FORMAT_R16G16B16A16_SFLOAT:

-			c.w = Float(*Pointer<Half>(element + 6));

-		case VK_FORMAT_R16G16B16_SFLOAT:

-			c.z = Float(*Pointer<Half>(element + 4));

-		case VK_FORMAT_R16G16_SFLOAT:

-			c.y = Float(*Pointer<Half>(element + 2));

-		case VK_FORMAT_R16_SFLOAT:

-			c.x = Float(*Pointer<Half>(element));

+		case VK_FORMAT_R16G16B16A16_SFLOAT:
+			c.w = Float(*Pointer<Half>(element + 6));
+		case VK_FORMAT_R16G16B16_SFLOAT:
+			c.z = Float(*Pointer<Half>(element + 4));
+		case VK_FORMAT_R16G16_SFLOAT:
+			c.y = Float(*Pointer<Half>(element + 2));
+		case VK_FORMAT_R16_SFLOAT:
+			c.x = Float(*Pointer<Half>(element));
 			break;
 		case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
 			// 10 (or 11) bit float formats are unsigned formats with a 5 bit exponent and a 5 (or 6) bit mantissa.
@@ -367,8 +367,8 @@
 			break;
 		case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
 			// This type contains a common 5 bit exponent (E) and a 9 bit the mantissa for R, G and B.
-			c.x = Float(*Pointer<UInt>(element) & UInt(0x000001FF));         // R's mantissa (bits 0-8)

-			c.y = Float((*Pointer<UInt>(element) & UInt(0x0003FE00)) >> 9);  // G's mantissa (bits 9-17)

+			c.x = Float(*Pointer<UInt>(element) & UInt(0x000001FF));         // R's mantissa (bits 0-8)
+			c.y = Float((*Pointer<UInt>(element) & UInt(0x0003FE00)) >> 9);  // G's mantissa (bits 9-17)
 			c.z = Float((*Pointer<UInt>(element) & UInt(0x07FC0000)) >> 18); // B's mantissa (bits 18-26)
 			c *= Float4(
 				// 2^E, using the exponent (bits 27-31) and treating it as an unsigned integer value
@@ -467,10 +467,10 @@
 		case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
 			if(writeRGBA)
 			{
-				*Pointer<UShort>(element) = UShort(RoundInt(Float(c.w)) & Int(0xF)) |

-				                            UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |

-				                            UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |

-				                            UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12);

+				*Pointer<UShort>(element) = UShort(RoundInt(Float(c.w)) & Int(0xF)) |
+				                            UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |
+				                            UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |
+				                            UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12);
 			}
 			else
 			{
@@ -480,9 +480,9 @@
 				                      (writeB ? 0xF000 : 0x0000);
 				unsigned short unmask = ~mask;
 				*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
-				                            ((UShort(RoundInt(Float(c.w)) & Int(0xF)) |

-				                              UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |

-				                              UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |

+				                            ((UShort(RoundInt(Float(c.w)) & Int(0xF)) |
+				                              UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |
+				                              UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |
 				                              UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12)) & UShort(mask));
 			}
 			break;
@@ -565,14 +565,14 @@
 		case VK_FORMAT_R32_SFLOAT:
 			if(writeR) { *Pointer<Float>(element) = c.x; }
 			break;
-		case VK_FORMAT_R16G16B16A16_SFLOAT:

-			if(writeA) { *Pointer<Half>(element + 6) = Half(c.w); }

-		case VK_FORMAT_R16G16B16_SFLOAT:

-			if(writeB) { *Pointer<Half>(element + 4) = Half(c.z); }

-		case VK_FORMAT_R16G16_SFLOAT:

-			if(writeG) { *Pointer<Half>(element + 2) = Half(c.y); }

-		case VK_FORMAT_R16_SFLOAT:

-			if(writeR) { *Pointer<Half>(element) = Half(c.x); }

+		case VK_FORMAT_R16G16B16A16_SFLOAT:
+			if(writeA) { *Pointer<Half>(element + 6) = Half(c.w); }
+		case VK_FORMAT_R16G16B16_SFLOAT:
+			if(writeB) { *Pointer<Half>(element + 4) = Half(c.z); }
+		case VK_FORMAT_R16G16_SFLOAT:
+			if(writeG) { *Pointer<Half>(element + 2) = Half(c.y); }
+		case VK_FORMAT_R16_SFLOAT:
+			if(writeR) { *Pointer<Half>(element) = Half(c.x); }
 			break;
 		case VK_FORMAT_B8G8R8A8_SNORM:
 			if(writeB) { *Pointer<SByte>(element) = SByte(RoundInt(Float(c.z))); }
@@ -1496,7 +1496,7 @@
 			if(!blitRoutine)
 			{
 				criticalSection.unlock();
-				UNIMPLEMENTED();
+				UNIMPLEMENTED("blitRoutine");
 				return nullptr;
 			}
 
@@ -1518,7 +1518,7 @@
 		if((region.srcSubresource.layerCount != region.dstSubresource.layerCount) ||
 		   (region.srcSubresource.aspectMask != region.dstSubresource.aspectMask))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("region");
 		}
 
 		if(region.dstOffsets[0].x > region.dstOffsets[1].x)
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index efcb928..bc1a29d 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -279,7 +279,7 @@
 						mainBlockId = Block::ID(it.word(1));
 						break;
 					default:
-						ERR("Unexpected opcode '%s' following OpFunction", OpcodeName(it.opcode()).c_str());
+						WARN("Unexpected opcode '%s' following OpFunction", OpcodeName(it.opcode()).c_str());
 					}
 				}
 				ASSERT(mainBlockId.value() != 0); // Function's OpLabel not found
@@ -424,7 +424,7 @@
 				break;
 
 			default:
-				UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str());
+				UNIMPLEMENTED("%s", OpcodeName(insn.opcode()).c_str());
 			}
 		}
 	}
@@ -1227,7 +1227,7 @@
 			break;
 
 		default:
-			UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str());
+			UNIMPLEMENTED("opcode: %s", OpcodeName(insn.opcode()).c_str());
 			break;
 		}
 	}
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 8f3c29f..1f5e075 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -392,14 +392,14 @@
 		Type const &getType(Type::ID id) const
 		{
 			auto it = types.find(id);
-			ASSERT(it != types.end());
+			ASSERT_MSG(it != types.end(), "Unknown type %d", id.value());
 			return it->second;
 		}
 
 		Object const &getObject(Object::ID id) const
 		{
 			auto it = defs.find(id);
-			ASSERT(it != defs.end());
+			ASSERT_MSG(it != defs.end(), "Unknown object %d", id.value());
 			return it->second;
 		}
 
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index c80483d..0421780 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -601,7 +601,7 @@
 
 	if(pInheritanceInfo)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pInheritanceInfo");
 	}
 
 	if(state != INITIAL)
@@ -646,7 +646,7 @@
 
 	if(contents != VK_SUBPASS_CONTENTS_INLINE)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("VK_SUBPASS_CONTENTS_INLINE");
 	}
 
 	addCommand<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
@@ -666,18 +666,18 @@
 
 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("executeCommands");
 }
 
 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setDeviceMask");
 }
 
 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
                                  uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("dispatchBase");
 }
 
 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
@@ -698,7 +698,7 @@
 			addCommand<PipelineBind>(pipelineBindPoint, pipeline);
 			break;
 		default:
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pipelineBindPoint");
 	}
 }
 
@@ -713,46 +713,46 @@
 
 void CommandBuffer::beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("beginQuery");
 }
 
 void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("endQuery");
 }
 
 void CommandBuffer::resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("resetQueryPool");
 }
 
 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("writeTimestamp");
 }
 
 void CommandBuffer::copyQueryPoolResults(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
 	VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("copyQueryPoolResults");
 }
 
 void CommandBuffer::pushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags,
 	uint32_t offset, uint32_t size, const void* pValues)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("pushConstants");
 }
 
 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports)
 {
 	// Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setViewport");
 }
 
 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors)
 {
 	// Note: The bound graphics pipeline must have been created with the VK_DYNAMIC_STATE_SCISSOR dynamic state enabled
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setScissor");
 }
 
 void CommandBuffer::setLineWidth(float lineWidth)
@@ -762,7 +762,7 @@
 	// If the wide lines feature is not enabled, lineWidth must be 1.0
 	ASSERT(lineWidth == 1.0f);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setLineWidth");
 }
 
 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
@@ -772,7 +772,7 @@
 	// If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0
 	ASSERT(depthBiasClamp == 0.0f);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setDepthBias");
 }
 
 void CommandBuffer::setBlendConstants(const float blendConstants[4])
@@ -782,7 +782,7 @@
 	// blendConstants is an array of four values specifying the R, G, B, and A components
 	// of the blend constant color used in blending, depending on the blend factor.
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setBlendConstants");
 }
 
 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
@@ -793,7 +793,7 @@
 	ASSERT(minDepthBounds >= 0.0f && minDepthBounds <= 1.0f);
 	ASSERT(maxDepthBounds >= 0.0f && maxDepthBounds <= 1.0f);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setDepthBounds");
 }
 
 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
@@ -803,7 +803,7 @@
 	// faceMask must not be 0
 	ASSERT(faceMask != 0);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setStencilCompareMask");
 }
 
 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
@@ -813,7 +813,7 @@
 	// faceMask must not be 0
 	ASSERT(faceMask != 0);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setStencilWriteMask");
 }
 
 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
@@ -823,7 +823,7 @@
 	// faceMask must not be 0
 	ASSERT(faceMask != 0);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("setStencilReference");
 }
 
 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
@@ -834,7 +834,7 @@
 
 	if(dynamicOffsetCount > 0)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("bindDescriptorSets");
 	}
 
 	for(uint32_t i = 0; i < descriptorSetCount; i++)
@@ -855,7 +855,7 @@
 
 void CommandBuffer::dispatchIndirect(VkBuffer buffer, VkDeviceSize offset)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("dispatchIndirect");
 }
 
 void CommandBuffer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)
@@ -974,7 +974,7 @@
 void CommandBuffer::resolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
 	uint32_t regionCount, const VkImageResolve* pRegions)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("resolveImage");
 }
 
 void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
@@ -996,7 +996,7 @@
 	uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
 	uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("waitEvents");
 }
 
 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
@@ -1011,12 +1011,12 @@
 
 void CommandBuffer::drawIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("drawIndirect");
 }
 
 void CommandBuffer::drawIndexedIndirect(VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
 {
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("drawIndexedIndirect");
 }
 
 void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState)
diff --git a/src/Vulkan/VkDebug.cpp b/src/Vulkan/VkDebug.cpp
index b82ef80..262f700 100644
--- a/src/Vulkan/VkDebug.cpp
+++ b/src/Vulkan/VkDebug.cpp
@@ -14,25 +14,61 @@
 
 #include "VkDebug.hpp"
 
+#include <string>
 #include <stdarg.h>
 
 namespace vk
 {
-void trace(const char *format, ...)
+
+void tracev(const char *format, va_list args)
 {
+#ifndef SWIFTSHADER_DISABLE_TRACE
 	if(false)
 	{
-		FILE *file = fopen("debug.txt", "a");
+		FILE *file = fopen(TRACE_OUTPUT_FILE, "a");
 
 		if(file)
 		{
-			va_list vararg;
-			va_start(vararg, format);
-			vfprintf(file, format, vararg);
-			va_end(vararg);
-
+			vfprintf(file, format, args);
 			fclose(file);
 		}
 	}
+#endif
 }
+
+void trace(const char *format, ...)
+{
+	va_list vararg;
+	va_start(vararg, format);
+	tracev(format, vararg);
+	va_end(vararg);
+}
+
+void warn(const char *format, ...)
+{
+	va_list vararg;
+	va_start(vararg, format);
+	tracev(format, vararg);
+	va_end(vararg);
+
+	va_start(vararg, format);
+	vfprintf(stderr, format, vararg);
+	va_end(vararg);
+}
+
+void abort(const char *format, ...)
+{
+	va_list vararg;
+
+	va_start(vararg, format);
+	tracev(format, vararg);
+	va_end(vararg);
+
+	va_start(vararg, format);
+	vfprintf(stderr, format, vararg);
+	va_end(vararg);
+
+	::abort();
+}
+
 }
diff --git a/src/Vulkan/VkDebug.hpp b/src/Vulkan/VkDebug.hpp
index 6bad986..3133932 100644
--- a/src/Vulkan/VkDebug.hpp
+++ b/src/Vulkan/VkDebug.hpp
@@ -27,77 +27,85 @@
 
 namespace vk
 {
-// Outputs text to the debugging log
-void trace(const char *format, ...);
-inline void trace() {}
+	// Outputs text to the debugging log
+	void trace(const char *format, ...);
+	inline void trace() {}
+
+	// Outputs text to the debugging log and prints to stderr.
+	void warn(const char *format, ...);
+	inline void warn() {}
+
+	// Outputs the message to the debugging log and stderr, and calls abort().
+	void abort(const char *format, ...);
 }
 
-// A macro to output a trace of a function call and its arguments to the debugging log
+// A macro to output a trace of a function call and its arguments to the
+// debugging log. Disabled if SWIFTSHADER_DISABLE_TRACE is defined.
 #if defined(SWIFTSHADER_DISABLE_TRACE)
 #define TRACE(message, ...) (void(0))
 #else
-#define TRACE(message, ...) vk::trace("trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define TRACE(message, ...) vk::trace("%s:%d TRACE: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
 #endif
 
-// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(SWIFTSHADER_DISABLE_TRACE)
-#define FIXME(message, ...) (void(0))
-#else
-#define FIXME(message, ...) do {vk::trace("fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); assert(false); abort();} while(false)
-#endif
+// A macro to print a warning message to the debugging log and stderr to denote
+// an issue that needs fixing.
+#define FIXME(message, ...) vk::warn("%s:%d FIXME: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__);
 
-// A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(SWIFTSHADER_DISABLE_TRACE)
-#define ERR(message, ...) (void(0))
-#else
-#define ERR(message, ...) do {vk::trace("err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); assert(false); abort();} while(false)
-#endif
+// A macro to print a warning message to the debugging log and stderr.
+#define WARN(message, ...) vk::warn("%s:%d WARNING: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__);
 
-// A macro asserting a condition and outputting failures to the debug log
-#undef ASSERT
+// A macro that prints the message to the debugging log and stderr and
+// immediately aborts execution of the application.
+//
+// Note: This will terminate the application regardless of build flags!
+//       Use with extreme caution!
+#undef ABORT
+#define ABORT(message, ...) vk::abort("%s:%d ABORT: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
+
+// A macro that delegates to:
+//   ABORT() in debug builds (!NDEBUG || DCHECK_ALWAYS_ON)
+// or
+//   WARN() in release builds (NDEBUG && !DCHECK_ALWAYS_ON)
+#undef DABORT
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+#define DABORT(message, ...) ABORT(message, ##__VA_ARGS__)
+#else
+#define DABORT(message, ...) WARN(message, ##__VA_ARGS__)
+#endif
+
+// A macro asserting a condition.
+// If the condition fails, the condition and message is passed to DABORT().
+#undef ASSERT_MSG
+#define ASSERT_MSG(expression, format, ...) do { \
+	if(!(expression)) { \
+		DABORT("ASSERT(%s): " format "\n", #expression, ##__VA_ARGS__); \
+	} } while(0)
+
+// A macro asserting a condition.
+// If the condition fails, the condition is passed to DABORT().
+#undef ASSERT
 #define ASSERT(expression) do { \
 	if(!(expression)) { \
-		ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
-		assert(expression); \
-		abort(); \
+		DABORT("ASSERT(%s)\n", #expression); \
 	} } while(0)
-#else
-#define ASSERT(expression) (void(0))
-#endif
 
-// A macro to indicate unimplemented functionality
+// A macro to indicate unimplemented functionality.
 #undef UNIMPLEMENTED
-#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
-#define UNIMPLEMENTED(...) do { \
-	vk::trace("\t! Unimplemented: %s(%d): ", __FUNCTION__, __LINE__); \
-	vk::trace(__VA_ARGS__); \
-	vk::trace("\n"); \
-	assert(false); \
-	abort(); \
-	} while(0)
-#else
-	#define UNIMPLEMENTED(...) FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNIMPLEMENTED(format, ...) DABORT("UNIMPLEMENTED: " format, ##__VA_ARGS__)
 
-// A macro for code which is not expected to be reached under valid assumptions
+// A macro for code which is not expected to be reached under valid assumptions.
 #undef UNREACHABLE
-#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
-#define UNREACHABLE(value) do { \
-	ERR("\t! Unreachable case reached: %s(%d). %s: %d\n", __FUNCTION__, __LINE__, #value, value); \
-	assert(false); \
-	abort(); \
-	} while(0)
-#else
-	#define UNREACHABLE(value) ERR("\t! Unreachable reached: %s(%d). %s: %d\n", __FUNCTION__, __LINE__, #value, value)
-#endif
+#define UNREACHABLE(format, ...) DABORT("UNREACHABLE: " format, ##__VA_ARGS__)
 
-// A macro asserting a condition and outputting failures to the debug log, or return when in release mode.
+// A macro asserting a condition and performing a return.
 #undef ASSERT_OR_RETURN
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+#define ASSERT_OR_RETURN(expression) ASSERT(expression)
+#else
 #define ASSERT_OR_RETURN(expression) do { \
 	if(!(expression)) { \
-		ASSERT(expression); \
 		return; \
 	} } while(0)
+#endif
 
 #endif   // VK_DEBUG_H_
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index dc18c81..3517768 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -204,7 +204,7 @@
 		return reinterpret_cast<const uint8_t*>(descriptorWrites.pBufferInfo);
 		break;
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("descriptorType");
 		return nullptr;
 	}
 }
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp
index 7891784..787c2aa 100644
--- a/src/Vulkan/VkDevice.cpp
+++ b/src/Vulkan/VkDevice.cpp
@@ -49,7 +49,7 @@
 	if(pCreateInfo->enabledLayerCount)
 	{
 		// "The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations."
-		UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+		UNIMPLEMENTED("enabledLayerCount");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 	}
 
 	blitter = new sw::Blitter();
@@ -90,12 +90,12 @@
 	// FIXME(b/117835459) : noop
 }
 
-void Device::waitIdle()

-{

-	for(uint32_t i = 0; i < queueCount; i++)

-	{

-		queues[i].waitIdle();

-	}

+void Device::waitIdle()
+{
+	for(uint32_t i = 0; i < queueCount; i++)
+	{
+		queues[i].waitIdle();
+	}
 }
 
 void Device::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 7c83f03..0702d6b 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -89,7 +89,7 @@
 		  (pSubresource->aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
 		  (pSubresource->aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("aspectMask");
 	}
 	auto aspect = static_cast<VkImageAspectFlagBits>(pSubresource->aspectMask);
 	pLayout->offset = getMemoryOffset(aspect, pSubresource->mipLevel, pSubresource->arrayLayer);
@@ -111,7 +111,7 @@
 		 (pRegion.srcSubresource.baseArrayLayer != 0) ||
 		 (pRegion.srcSubresource.layerCount != 1))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("srcSubresource");
 	}
 
 	if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
@@ -120,7 +120,7 @@
 		 (pRegion.dstSubresource.baseArrayLayer != 0) ||
 		 (pRegion.dstSubresource.layerCount != 1))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("dstSubresource");
 	}
 
 	VkImageAspectFlagBits srcAspect = static_cast<VkImageAspectFlagBits>(pRegion.srcSubresource.aspectMask);
@@ -210,7 +210,7 @@
 	     (region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
 	     (region.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("imageSubresource");
 	}
 
 	VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(region.imageSubresource.aspectMask);
@@ -541,7 +541,7 @@
 	if((subresourceRange.baseMipLevel != 0) ||
 	   (subresourceRange.levelCount != 1))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("subresourceRange");
 	}
 
 	device->getBlitter()->clear(pixelData, format, this, subresourceRange, &renderArea);
@@ -551,7 +551,7 @@
 {
 	if(!(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("aspectMask");
 	}
 
 	device->getBlitter()->clear((void*)color.float32, getClearFormat(), this, subresourceRange);
@@ -562,7 +562,7 @@
 	if((subresourceRange.aspectMask & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
 	                                    VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("aspectMask");
 	}
 
 	if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
@@ -588,7 +588,7 @@
 	   (subresourceRange.baseMipLevel != 0) ||
 	   (subresourceRange.levelCount != 1))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("subresourceRange");
 	}
 
 	if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 205cbed..ca73f5d 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -84,12 +84,12 @@
 
 	if(!imageTypesMatch(image->getImageType()))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("imageTypesMatch");
 	}
 
 	if(image->getFormat() != format)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("format");
 	}
 
 	VkImageSubresourceRange sr = subresourceRange;
@@ -103,12 +103,12 @@
 
 	if(!imageTypesMatch(image->getImageType()))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("imageTypesMatch");
 	}
 
 	if(image->getFormat() != format)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("format");
 	}
 
 	VkImageSubresourceRange sr;
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index f700a32..95cf71d 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -655,7 +655,7 @@
 		pImageFormatProperties->maxArrayLayers = 1;		// no 3D + layers
 		break;
 	default:
-		UNREACHABLE(type);
+		UNREACHABLE("VkImageType: %d", int(type));
 		break;
 	}
 
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 17580d6..5cd45ce 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -53,7 +53,7 @@
 		ASSERT(false);
 		break;
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("topology");
 	}
 
 	return sw::DRAW_TRIANGLELIST;
@@ -119,7 +119,7 @@
 	case VK_FORMAT_R32G32B32A32_SFLOAT:
 		return sw::STREAMTYPE_FLOAT;
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("format");
 	}
 
 	return sw::STREAMTYPE_BYTE;
@@ -179,7 +179,7 @@
 	case VK_FORMAT_R32G32B32A32_SFLOAT:
 		return 4;
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("format");
 	}
 
 	return 0;
@@ -194,19 +194,17 @@
 	spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1};
 
 	opt.SetMessageConsumer([](spv_message_level_t level, const char*, const spv_position_t& p, const char* m) {
+		const char* category = "";
 		switch (level)
 		{
-		case SPV_MSG_FATAL:
-		case SPV_MSG_INTERNAL_ERROR:
-		case SPV_MSG_ERROR:
-			ERR("%d:%d %s", p.line, p.column, m);
-			break;
-		case SPV_MSG_WARNING:
-		case SPV_MSG_INFO:
-		case SPV_MSG_DEBUG:
-			TRACE("%d:%d %s", p.line, p.column, m);
-			break;
+		case SPV_MSG_FATAL:          category = "FATAL";          break;
+		case SPV_MSG_INTERNAL_ERROR: category = "INTERNAL_ERROR"; break;
+		case SPV_MSG_ERROR:          category = "ERROR";          break;
+		case SPV_MSG_WARNING:        category = "WARNING";        break;
+		case SPV_MSG_INFO:           category = "INFO";           break;
+		case SPV_MSG_DEBUG:          category = "DEBUG";          break;
 		}
+		vk::trace("%s: %d:%d %s", category, p.line, p.column, m);
 	});
 
 	opt.RegisterPass(spvtools::CreateInlineExhaustivePass());
@@ -264,13 +262,13 @@
 	   (pCreateInfo->basePipelineHandle != VK_NULL_HANDLE) ||
 	   (pCreateInfo->basePipelineIndex != 0))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo settings");
 	}
 
 	const VkPipelineVertexInputStateCreateInfo* vertexInputState = pCreateInfo->pVertexInputState;
 	if(vertexInputState->flags != 0)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("vertexInputState->flags");
 	}
 
 	// Context must always have a PipelineLayout set.
@@ -285,7 +283,7 @@
 		bufferStrides[desc.binding] = desc.stride;
 		if(desc.inputRate != VK_VERTEX_INPUT_RATE_VERTEX)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("vertexInputState->pVertexBindingDescriptions[%d]", i);
 		}
 	}
 
@@ -305,7 +303,7 @@
 	if((assemblyState->flags != 0) ||
 	   (assemblyState->primitiveRestartEnable != 0))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pInputAssemblyState settings");
 	}
 
 	context.drawType = Convert(assemblyState->topology);
@@ -317,7 +315,7 @@
 			(viewportState->viewportCount != 1) ||
 			(viewportState->scissorCount != 1))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pCreateInfo->pViewportState settings");
 		}
 
 		scissor = viewportState->pScissors[0];
@@ -329,7 +327,7 @@
 	   (rasterizationState->depthClampEnable != 0) ||
 	   (rasterizationState->polygonMode != VK_POLYGON_MODE_FILL))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pRasterizationState settings");
 	}
 
 	context.rasterizerDiscard = rasterizationState->rasterizerDiscardEnable;
@@ -359,7 +357,7 @@
 				(multisampleState->alphaToCoverageEnable != 0) ||
 			(multisampleState->alphaToOneEnable != 0))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("multisampleState");
 		}
 	}
 	else
@@ -373,7 +371,7 @@
 		if((depthStencilState->flags != 0) ||
 		   (depthStencilState->depthBoundsTestEnable != 0))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("depthStencilState");
 		}
 
 		context.depthBufferEnable = depthStencilState->depthTestEnable;
@@ -408,7 +406,7 @@
 		   ((colorBlendState->logicOpEnable != 0) &&
 			(colorBlendState->attachmentCount > 1)))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("colorBlendState");
 		}
 
 		blendConstants.r = colorBlendState->blendConstants[0];
@@ -421,7 +419,7 @@
 			const VkPipelineColorBlendAttachmentState& attachment = colorBlendState->pAttachments[0];
 			if(attachment.colorWriteMask != (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT))
 			{
-				UNIMPLEMENTED();
+				UNIMPLEMENTED("colorWriteMask");
 			}
 
 			context.alphaBlendEnable = attachment.blendEnable;
@@ -455,7 +453,7 @@
 	{
 		if (pStage->flags != 0)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pStage->flags");
 		}
 
 		auto module = Cast(pStage->module);
@@ -497,7 +495,7 @@
 	case sw::DRAW_TRIANGLEFAN:
 		return vertexCount - 2;
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("drawType");
 	}
 
 	return 0;
diff --git a/src/Vulkan/VkQueryPool.cpp b/src/Vulkan/VkQueryPool.cpp
index 8a63208..da4627a 100644
--- a/src/Vulkan/VkQueryPool.cpp
+++ b/src/Vulkan/VkQueryPool.cpp
@@ -27,7 +27,7 @@
 		//  pipelineStatistics member of the VkQueryPoolCreateInfo structure."
 		if(pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pCreateInfo->queryType");
 		}
 	}
 
@@ -48,7 +48,7 @@
 		char* data = static_cast<char*>(pData);
 		for(uint32_t i = 0; i < pQueryCount; i++, data += pStride)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("queries");
 		}
 	}
 } // namespace vk
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index f86d9d6..bf07cf1 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -110,7 +110,7 @@
 
 	if(pCreateInfo->enabledLayerCount)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->enabledLayerCount");
 	}
 
 	for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; ++i)
@@ -146,7 +146,7 @@
 			//  Vulkan structures in this Specification."
 			break;
 		default:
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pCreateInfo->pNext");
 		}
 	}
 
@@ -234,7 +234,7 @@
 		break;
 
 	default:
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("tiling");
 	}
 
 	vk::Cast(physicalDevice)->getImageFormatProperties(format, type, tiling, usage, flags, pImageFormatProperties);
@@ -293,7 +293,7 @@
 	if(pCreateInfo->enabledLayerCount)
 	{
 		// "The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations."
-		UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+		UNIMPLEMENTED("pCreateInfo->enabledLayerCount");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 	}
 
 
@@ -391,7 +391,7 @@
 			break;
 		default:
 			// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
-			UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+			UNIMPLEMENTED("extensionCreateInfo->sType");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 			break;
 		}
 
@@ -404,7 +404,7 @@
 	{
 		if(!vk::Cast(physicalDevice)->hasFeatures(*(pCreateInfo->pEnabledFeatures)))
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pCreateInfo->pEnabledFeatures");
 			return VK_ERROR_FEATURE_NOT_PRESENT;
 		}
 	}
@@ -416,7 +416,7 @@
 		const VkDeviceQueueCreateInfo& queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
 		if(queueCreateInfo.pNext || queueCreateInfo.flags)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("queueCreateInfo.pNext || queueCreateInfo.flags");
 		}
 
 		ASSERT(queueCreateInfo.queueFamilyIndex < queueFamilyPropertyCount);
@@ -558,7 +558,7 @@
 			//  includes a handle of the sole buffer or image resource that the memory *can* be bound to."
 			break;
 		default:
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("allocationInfo->sType");
 			break;
 		}
 
@@ -700,7 +700,7 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkQueueBindSparse");
 	return VK_SUCCESS;
 }
 
@@ -711,7 +711,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	return vk::Fence::Create(pAllocator, pCreateInfo, pFence);
@@ -763,7 +763,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::Semaphore::Create(pAllocator, pCreateInfo, pSemaphore);
@@ -784,7 +784,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::Event::Create(pAllocator, pCreateInfo, pEvent);
@@ -830,7 +830,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::QueryPool::Create(pAllocator, pCreateInfo, pQueryPool);
@@ -861,7 +861,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	return vk::Buffer::Create(pAllocator, pCreateInfo, pBuffer);
@@ -882,7 +882,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::BufferView::Create(pAllocator, pCreateInfo, pView);
@@ -903,7 +903,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	vk::Image::CreateInfo imageCreateInfo =
@@ -938,7 +938,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::ImageView::Create(pAllocator, pCreateInfo, pView);
@@ -959,7 +959,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::ShaderModule::Create(pAllocator, pCreateInfo, pShaderModule);
@@ -980,7 +980,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::PipelineCache::Create(pAllocator, pCreateInfo, pPipelineCache);
@@ -997,14 +997,14 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkGetPipelineCacheData");
 	return VK_SUCCESS;
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkMergePipelineCaches");
 	return VK_SUCCESS;
 }
 
@@ -1089,7 +1089,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::PipelineLayout::Create(pAllocator, pCreateInfo, pPipelineLayout);
@@ -1110,7 +1110,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::Sampler::Create(pAllocator, pCreateInfo, pSampler);
@@ -1131,7 +1131,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	return vk::DescriptorSetLayout::Create(pAllocator, pCreateInfo, pSetLayout);
@@ -1152,7 +1152,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	return vk::DescriptorPool::Create(pAllocator, pCreateInfo, pDescriptorPool);
@@ -1173,7 +1173,7 @@
 
 	if(flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("flags");
 	}
 
 	return vk::Cast(descriptorPool)->reset();
@@ -1186,7 +1186,7 @@
 
 	if(pAllocateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pAllocateInfo->pNext");
 	}
 
 	return vk::Cast(pAllocateInfo->descriptorPool)->allocateSets(
@@ -1218,7 +1218,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::Framebuffer::Create(pAllocator, pCreateInfo, pFramebuffer);
@@ -1238,7 +1238,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags");
 	}
 
 	return vk::RenderPass::Create(pAllocator, pCreateInfo, pRenderPass);
@@ -1267,7 +1267,7 @@
 
 	if(pCreateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext");
 	}
 
 	return vk::CommandPool::Create(pAllocator, pCreateInfo, pCommandPool);
@@ -1296,7 +1296,7 @@
 
 	if(pAllocateInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pAllocateInfo->pNext");
 	}
 
 	return vk::Cast(pAllocateInfo->commandPool)->allocateCommandBuffers(
@@ -1318,7 +1318,7 @@
 
 	if(pBeginInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pBeginInfo->pNext");
 	}
 
 	return vk::Cast(commandBuffer)->begin(pBeginInfo->flags, pBeginInfo->pInheritanceInfo);
@@ -1668,7 +1668,7 @@
 
 	if(pRenderPassBegin->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pRenderPassBegin->pNext");
 	}
 
 	vk::Cast(commandBuffer)->beginRenderPass(pRenderPassBegin->renderPass, pRenderPassBegin->framebuffer,
@@ -1715,7 +1715,7 @@
 	{
 		if(pBindInfos[i].pNext)
 		{
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("pBindInfos[%d].pNext", i);
 		}
 
 		vk::Cast(pBindInfos[i].buffer)->bind(pBindInfos[i].memory, pBindInfos[i].memoryOffset);
@@ -1727,7 +1727,7 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkBindImageMemory2");
 	return VK_SUCCESS;
 }
 
@@ -1737,19 +1737,19 @@
 	      device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
 
 	ASSERT(localDeviceIndex != remoteDeviceIndex); // "localDeviceIndex must not equal remoteDeviceIndex"
-	UNREACHABLE(remoteDeviceIndex);   // Only one physical device is supported, and since the device indexes can't be equal, this should never be called.
+	UNREACHABLE("remoteDeviceIndex: %d", int(remoteDeviceIndex));   // Only one physical device is supported, and since the device indexes can't be equal, this should never be called.
 }
 
 VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkCmdSetDeviceMask");
 }
 
 VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkCmdDispatchBase");
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
@@ -1776,7 +1776,7 @@
 
 	if(pInfo->pNext || pMemoryRequirements->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pInfo->pNext || pMemoryRequirements->pNext");
 	}
 
 	vkGetImageMemoryRequirements(device, pInfo->image, &(pMemoryRequirements->memoryRequirements));
@@ -1789,7 +1789,7 @@
 
 	if(pInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pInfo->pNext");
 	}
 
 	VkBaseOutStructure* extensionRequirements = reinterpret_cast<VkBaseOutStructure*>(pMemoryRequirements->pNext);
@@ -1805,7 +1805,7 @@
 			}
 			break;
 		default:
-			UNIMPLEMENTED();
+			UNIMPLEMENTED("extensionRequirements->sType");
 			break;
 		}
 
@@ -1822,7 +1822,7 @@
 
 	if(pInfo->pNext || pSparseMemoryRequirements->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pInfo->pNext || pSparseMemoryRequirements->pNext");
 	}
 
 	vkGetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, &(pSparseMemoryRequirements->memoryRequirements));
@@ -1875,7 +1875,7 @@
 			break;
 		default:
 			// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
-			UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+			UNIMPLEMENTED("extensionFeatures->sType");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 			break;
 		}
 
@@ -1932,7 +1932,7 @@
 			break;
 		default:
 			// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
-			UNIMPLEMENTED();   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+			UNIMPLEMENTED("extensionProperties->sType");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
 			break;
 		}
 
@@ -1949,7 +1949,7 @@
 
 	if(pFormatProperties->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pFormatProperties->pNext");
 	}
 
 	vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &(pFormatProperties->formatProperties));
@@ -1962,7 +1962,7 @@
 
 	if(pImageFormatInfo->pNext || pImageFormatProperties->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pImageFormatInfo->pNext || pImageFormatProperties->pNext");
 	}
 
 	return vkGetPhysicalDeviceImageFormatProperties(physicalDevice,
@@ -1981,7 +1981,7 @@
 
 	if(pQueueFamilyProperties && pQueueFamilyProperties->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pQueueFamilyProperties->pNext");
 	}
 
 	vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
@@ -1994,7 +1994,7 @@
 
 	if(pMemoryProperties->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pMemoryProperties->pNext");
 	}
 
 	vkGetPhysicalDeviceMemoryProperties(physicalDevice, &(pMemoryProperties->memoryProperties));
@@ -2007,7 +2007,7 @@
 
 	if(pProperties && pProperties->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pProperties->pNext");
 	}
 
 	vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type,
@@ -2030,7 +2030,7 @@
 
 	if(pQueueInfo->pNext)
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pQueueInfo->pNext");
 	}
 
 	// The only flag that can be set here is VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT
@@ -2051,14 +2051,14 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkCreateSamplerYcbcrConversion");
 	return VK_SUCCESS;
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator)
 {
 	TRACE("()");
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkDestroySamplerYcbcrConversion");
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate)
@@ -2068,7 +2068,7 @@
 
 	if(pCreateInfo->pNext || pCreateInfo->flags || (pCreateInfo->templateType != VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET))
 	{
-		UNIMPLEMENTED();
+		UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags || (pCreateInfo->templateType != VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET)");
 	}
 
 	return vk::DescriptorUpdateTemplate::Create(pAllocator, pCreateInfo, pDescriptorUpdateTemplate);
@@ -2095,7 +2095,7 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo = 0x%X, VkExternalBufferProperties* pExternalBufferProperties = 0x%X)",
 	      physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkGetPhysicalDeviceExternalBufferProperties");
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties)
@@ -2103,7 +2103,7 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo = 0x%X, VkExternalFenceProperties* pExternalFenceProperties = 0x%X)",
 	      physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkGetPhysicalDeviceExternalFenceProperties");
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties)
@@ -2111,7 +2111,7 @@
 	TRACE("(VkPhysicalDevice physicalDevice = 0x%X, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo = 0x%X, VkExternalSemaphoreProperties* pExternalSemaphoreProperties = 0x%X)",
 	      physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
 
-	UNIMPLEMENTED();
+	UNIMPLEMENTED("vkGetPhysicalDeviceExternalSemaphoreProperties");
 }
 
 VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport)