Vulkan: Add PipelineDesc.

The PipelineDesc class is a 512-byte packed description of the entire
Vulkan pipeline state. It uses the alignas keyword and some static
asserts to verify that the structures are packed. This ensures that
when ANGLE uses MurmurHash to hash the entire struct, and memcmp to
check for identity, that there are no garbage padding bits.

This CL does not implement the Pipeline cache, but it will help, since
now we have a packed type that can be used as the key to a hash map.

Bug: angleproject:2163
Change-Id: I16efa927f08d30d89a9c4c8943edd211c6878ac8
Reviewed-on: https://chromium-review.googlesource.com/829893
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index 9e15ee7..f23778c 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -167,6 +167,8 @@
 
     mLinkedFragmentModule.destroy(device);
     mLinkedVertexModule.destroy(device);
+    mVertexModuleSerial   = Serial();
+    mFragmentModuleSerial = Serial();
 
     // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
     mDescriptorSets.clear();
@@ -228,6 +230,7 @@
         vertexShaderInfo.pCode    = vertexCode.data();
 
         ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
+        mVertexModuleSerial = renderer->issueProgramSerial();
     }
 
     {
@@ -239,6 +242,7 @@
         fragmentShaderInfo.pCode    = fragmentCode.data();
 
         ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
+        mFragmentModuleSerial = renderer->issueProgramSerial();
     }
 
     ANGLE_TRY(initDescriptorSets(contextVk));
@@ -546,12 +550,22 @@
     return mLinkedVertexModule;
 }
 
+Serial ProgramVk::getVertexModuleSerial() const
+{
+    return mVertexModuleSerial;
+}
+
 const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
 {
     ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
     return mLinkedFragmentModule;
 }
 
+Serial ProgramVk::getFragmentModuleSerial() const
+{
+    return mFragmentModuleSerial;
+}
+
 vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
 {
     ASSERT(mDescriptorSets.empty());