Implement VK_KHR_vulkan_memory_model

This is largely a no-op because CPUs typically have fully coherent
cache hierarchies (including on ccNUMA systems). Thus every write is
implicitly 'visible'. Atomic operations with memory-order semantics
likewise have system-wide 'scope'. And we don't support spare images yet
so 'availability' operations don't do anything.

Note that cache coherency would be lost if we were to use non-temporal
store instructions (e.g. MOVNTPS). A 'visibility' operation would
require inserting an SFENCE instruction.

The `VolatileTexel` image operand signifies that "This access cannot be
eliminated, duplicated, or combined with other accesses." There doesn't
appear to be dEQP-VK test coverage for it at this time, which makes it
non-trivial to optimally design how to handle it. It is therefore not
implemented at this time.

Bug: b/176819536
Tests: dEQP-VK.memory_model.*
Change-Id: Ifa97eed5a4506eef8ba77b8fb2042a0b1a624db5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/56209
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Commit-Queue: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 6a0134f..264a471 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -419,6 +419,8 @@
 				case spv::CapabilityDeviceGroup: capabilities.DeviceGroup = true; break;
 				case spv::CapabilityMultiView: capabilities.MultiView = true; break;
 				case spv::CapabilityStencilExportEXT: capabilities.StencilExportEXT = true; break;
+				case spv::CapabilityVulkanMemoryModel: capabilities.VulkanMemoryModel = true; break;
+				case spv::CapabilityVulkanMemoryModelDeviceScope: capabilities.VulkanMemoryModelDeviceScope = true; break;
 				default:
 					UNSUPPORTED("Unsupported capability %u", insn.word(1));
 				}
@@ -428,7 +430,11 @@
 			break;
 
 		case spv::OpMemoryModel:
-			break;  // Memory model does not affect our code generation until we decide to do Vulkan Memory Model support.
+			{
+				addressingModel = static_cast<spv::AddressingModel>(insn.word(1));
+				memoryModel = static_cast<spv::MemoryModel>(insn.word(2));
+			}
+			break;
 
 		case spv::OpFunction:
 			{
@@ -745,7 +751,7 @@
 
 		case spv::OpExtension:
 			{
-				auto ext = insn.string(1);
+				const char *ext = insn.string(1);
 				// Part of core SPIR-V 1.3. Vulkan 1.1 implementations must also accept the pre-1.3
 				// extension per Appendix A, `Vulkan Environment for SPIR-V`.
 				if(!strcmp(ext, "SPV_KHR_storage_buffer_storage_class")) break;
@@ -756,6 +762,7 @@
 				if(!strcmp(ext, "SPV_KHR_multiview")) break;
 				if(!strcmp(ext, "SPV_EXT_shader_stencil_export")) break;
 				if(!strcmp(ext, "SPV_KHR_float_controls")) break;
+				if(!strcmp(ext, "SPV_KHR_vulkan_memory_model")) break;
 				UNSUPPORTED("SPIR-V Extension: %s", ext);
 			}
 			break;