SPV: Add support for memory qualifiers.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 21a04b0..cebc747 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -265,6 +265,21 @@
     return (spv::Decoration)spv::BadValue;
 }
 
+// Translate glslang type to SPIR-V memory decorations.
+void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory)
+{
+    if (qualifier.coherent)
+        memory.push_back(spv::DecorationCoherent);
+    if (qualifier.volatil)
+        memory.push_back(spv::DecorationVolatile);
+    if (qualifier.restrict)
+        memory.push_back(spv::DecorationRestrict);
+    if (qualifier.readonly)
+        memory.push_back(spv::DecorationNonWritable);
+    if (qualifier.writeonly)
+       memory.push_back(spv::DecorationNonReadable);
+}
+
 // Translate glslang type to SPIR-V layout decorations.
 spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
 {
@@ -535,6 +550,16 @@
         child.patch = true;
     if (parent.sample)
         child.sample = true;
+    if (parent.coherent)
+        child.coherent = true;
+    if (parent.volatil)
+        child.volatil = true;
+    if (parent.restrict)
+        child.restrict = true;
+    if (parent.readonly)
+        child.readonly = true;
+    if (parent.writeonly)
+        child.writeonly = true;
 }
 
 bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier)
@@ -1759,6 +1784,13 @@
                     addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
                     addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
 
+                    if (qualifier.storage == glslang::EvqBuffer) {
+                        std::vector<spv::Decoration> memory;
+                        TranslateMemoryDecoration(subQualifier, memory);
+                        for (unsigned int i = 0; i < memory.size(); ++i)
+                            addMemberDecoration(spvType, member, memory[i]);
+                    }
+
                     // compute location decoration; tricky based on whether inheritance is at play
                     // TODO: This algorithm (and it's cousin above doing almost the same thing) should
                     //       probably move to the linker stage of the front end proper, and just have the
@@ -3575,6 +3607,13 @@
             builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
     }
 
+    if (symbol->getType().isImage()) {
+        std::vector<spv::Decoration> memory;
+        TranslateMemoryDecoration(symbol->getType().getQualifier(), memory);
+        for (unsigned int i = 0; i < memory.size(); ++i)
+            addDecoration(id, memory[i]);
+    }
+
     // built-in variable decorations
     spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn);
     if (builtIn != spv::BadValue)
diff --git a/Test/baseResults/spv.double.comp.out b/Test/baseResults/spv.double.comp.out
index fcd2f02..766f839 100755
--- a/Test/baseResults/spv.double.comp.out
+++ b/Test/baseResults/spv.double.comp.out
@@ -35,6 +35,7 @@
                               Decorate 26(gl_GlobalInvocationID) BuiltIn GlobalInvocationId
                               Decorate 33(gl_LocalInvocationID) BuiltIn LocalInvocationId
                               Decorate 59(destTex) DescriptorSet 0
+                              Decorate 59(destTex) NonReadable
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
diff --git a/Test/baseResults/spv.image.frag.out b/Test/baseResults/spv.image.frag.out
index 9cb1ec4..2bd26f7 100644
--- a/Test/baseResults/spv.image.frag.out
+++ b/Test/baseResults/spv.image.frag.out
@@ -79,6 +79,7 @@
                               Decorate 248(value) Flat
                               Decorate 357(wo2D) DescriptorSet 0
                               Decorate 357(wo2D) Binding 1
+                              Decorate 357(wo2D) NonReadable
                               Decorate 377(ic4D) Flat
                2:             TypeVoid
                3:             TypeFunction 2
diff --git a/Test/baseResults/spv.memoryQualifier.frag.out b/Test/baseResults/spv.memoryQualifier.frag.out
new file mode 100644
index 0000000..e2bfb39
--- /dev/null
+++ b/Test/baseResults/spv.memoryQualifier.frag.out
@@ -0,0 +1,181 @@
+spv.memoryQualifier.frag
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 97
+
+                              Capability Shader
+                              Capability SampledRect
+                              Capability Sampled1D
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "texel"
+                              Name 12  "i1D"
+                              Name 19  "i2D"
+                              Name 28  "i2DRect"
+                              Name 35  "i3D"
+                              Name 44  "iCube"
+                              Name 49  "Data"
+                              MemberName 49(Data) 0  "f1"
+                              MemberName 49(Data) 1  "f2"
+                              Name 50  "Buffer"
+                              MemberName 50(Buffer) 0  "f1"
+                              MemberName 50(Buffer) 1  "f2"
+                              MemberName 50(Buffer) 2  "f3"
+                              MemberName 50(Buffer) 3  "f4"
+                              MemberName 50(Buffer) 4  "i1"
+                              MemberName 50(Buffer) 5  "data"
+                              Name 52  ""
+                              Decorate 12(i1D) DescriptorSet 0
+                              Decorate 12(i1D) Binding 0
+                              Decorate 12(i1D) Coherent
+                              Decorate 19(i2D) DescriptorSet 0
+                              Decorate 19(i2D) Binding 1
+                              Decorate 19(i2D) Volatile
+                              Decorate 28(i2DRect) DescriptorSet 0
+                              Decorate 28(i2DRect) Binding 2
+                              Decorate 28(i2DRect) Restrict
+                              Decorate 35(i3D) DescriptorSet 0
+                              Decorate 35(i3D) Binding 3
+                              Decorate 35(i3D) NonWritable
+                              Decorate 44(iCube) DescriptorSet 0
+                              Decorate 44(iCube) Binding 3
+                              Decorate 44(iCube) NonReadable
+                              MemberDecorate 49(Data) 0 Coherent
+                              MemberDecorate 49(Data) 0 Offset 0
+                              MemberDecorate 49(Data) 1 Coherent
+                              MemberDecorate 49(Data) 1 Offset 8
+                              MemberDecorate 50(Buffer) 0 Coherent
+                              MemberDecorate 50(Buffer) 0 Volatile
+                              MemberDecorate 50(Buffer) 0 Offset 0
+                              MemberDecorate 50(Buffer) 1 Coherent
+                              MemberDecorate 50(Buffer) 1 Restrict
+                              MemberDecorate 50(Buffer) 1 Offset 8
+                              MemberDecorate 50(Buffer) 2 Coherent
+                              MemberDecorate 50(Buffer) 2 NonWritable
+                              MemberDecorate 50(Buffer) 2 Offset 16
+                              MemberDecorate 50(Buffer) 3 Coherent
+                              MemberDecorate 50(Buffer) 3 NonReadable
+                              MemberDecorate 50(Buffer) 3 Offset 32
+                              MemberDecorate 50(Buffer) 4 Coherent
+                              MemberDecorate 50(Buffer) 4 Offset 48
+                              MemberDecorate 50(Buffer) 5 Coherent
+                              MemberDecorate 50(Buffer) 5 Offset 56
+                              Decorate 50(Buffer) BufferBlock
+                              Decorate 52 DescriptorSet 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Function 7(fvec4)
+              10:             TypeImage 6(float) 1D nonsampled format:R32f
+              11:             TypePointer UniformConstant 10
+         12(i1D):     11(ptr) Variable UniformConstant
+              14:             TypeInt 32 1
+              15:     14(int) Constant 1
+              17:             TypeImage 6(float) 2D nonsampled format:R32f
+              18:             TypePointer UniformConstant 17
+         19(i2D):     18(ptr) Variable UniformConstant
+              21:             TypeVector 14(int) 2
+              22:   21(ivec2) ConstantComposite 15 15
+              26:             TypeImage 6(float) Rect nonsampled format:R32f
+              27:             TypePointer UniformConstant 26
+     28(i2DRect):     27(ptr) Variable UniformConstant
+              33:             TypeImage 6(float) 3D nonsampled format:R32f
+              34:             TypePointer UniformConstant 33
+         35(i3D):     34(ptr) Variable UniformConstant
+              37:             TypeVector 14(int) 3
+              38:   37(ivec3) ConstantComposite 15 15 15
+              42:             TypeImage 6(float) Cube nonsampled format:R32f
+              43:             TypePointer UniformConstant 42
+       44(iCube):     43(ptr) Variable UniformConstant
+              47:             TypeVector 6(float) 2
+              48:             TypeVector 6(float) 3
+        49(Data):             TypeStruct 6(float) 47(fvec2)
+      50(Buffer):             TypeStruct 6(float) 47(fvec2) 48(fvec3) 7(fvec4) 14(int) 49(Data)
+              51:             TypePointer Uniform 50(Buffer)
+              52:     51(ptr) Variable Uniform
+              53:     14(int) Constant 4
+              54:             TypePointer Uniform 14(int)
+              57:     14(int) Constant 0
+              58:             TypePointer Uniform 6(float)
+              61:             TypePointer Function 6(float)
+              63:             TypePointer Uniform 47(fvec2)
+              71:     14(int) Constant 2
+              72:             TypePointer Uniform 48(fvec3)
+              80:     14(int) Constant 5
+              83:             TypeInt 32 0
+              84:     83(int) Constant 1
+              88:     83(int) Constant 3
+              93:     14(int) Constant 3
+              95:             TypePointer Uniform 7(fvec4)
+         4(main):           2 Function None 3
+               5:             Label
+        9(texel):      8(ptr) Variable Function
+              13:          10 Load 12(i1D)
+              16:    7(fvec4) ImageRead 13 15
+                              Store 9(texel) 16
+              20:          17 Load 19(i2D)
+              23:    7(fvec4) ImageRead 20 22
+              24:    7(fvec4) Load 9(texel)
+              25:    7(fvec4) FAdd 24 23
+                              Store 9(texel) 25
+              29:          26 Load 28(i2DRect)
+              30:    7(fvec4) ImageRead 29 22
+              31:    7(fvec4) Load 9(texel)
+              32:    7(fvec4) FAdd 31 30
+                              Store 9(texel) 32
+              36:          33 Load 35(i3D)
+              39:    7(fvec4) ImageRead 36 38
+              40:    7(fvec4) Load 9(texel)
+              41:    7(fvec4) FAdd 40 39
+                              Store 9(texel) 41
+              45:          42 Load 44(iCube)
+              46:    7(fvec4) Load 9(texel)
+                              ImageWrite 45 38 46
+              55:     54(ptr) AccessChain 52 53
+              56:     14(int) Load 55
+              59:     58(ptr) AccessChain 52 57
+              60:    6(float) Load 59
+              62:     61(ptr) AccessChain 9(texel) 56
+                              Store 62 60
+              64:     63(ptr) AccessChain 52 15
+              65:   47(fvec2) Load 64
+              66:    7(fvec4) Load 9(texel)
+              67:   47(fvec2) VectorShuffle 66 66 0 1
+              68:   47(fvec2) FAdd 67 65
+              69:    7(fvec4) Load 9(texel)
+              70:    7(fvec4) VectorShuffle 69 68 4 5 2 3
+                              Store 9(texel) 70
+              73:     72(ptr) AccessChain 52 71
+              74:   48(fvec3) Load 73
+              75:    7(fvec4) Load 9(texel)
+              76:   48(fvec3) VectorShuffle 75 75 0 1 2
+              77:   48(fvec3) FSub 76 74
+              78:    7(fvec4) Load 9(texel)
+              79:    7(fvec4) VectorShuffle 78 77 4 5 6 3
+                              Store 9(texel) 79
+              81:     58(ptr) AccessChain 52 80 57
+              82:    6(float) Load 81
+              85:     58(ptr) AccessChain 52 80 15 84
+              86:    6(float) Load 85
+              87:    6(float) FAdd 82 86
+              89:     61(ptr) AccessChain 9(texel) 88
+              90:    6(float) Load 89
+              91:    6(float) FAdd 90 87
+              92:     61(ptr) AccessChain 9(texel) 88
+                              Store 92 91
+              94:    7(fvec4) Load 9(texel)
+              96:     95(ptr) AccessChain 52 93
+                              Store 96 94
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.memoryQualifier.frag b/Test/spv.memoryQualifier.frag
new file mode 100644
index 0000000..85e7147
--- /dev/null
+++ b/Test/spv.memoryQualifier.frag
@@ -0,0 +1,38 @@
+#version 450

+

+layout(binding = 0, r32f) uniform coherent image1D      i1D;

+layout(binding = 1, r32f) uniform volatile image2D      i2D;

+layout(binding = 2, r32f) uniform restrict image2DRect  i2DRect;

+layout(binding = 3, r32f) uniform readonly image3D      i3D;

+layout(binding = 3, r32f) uniform writeonly imageCube   iCube;

+

+struct Data

+{

+    float f1;

+    vec2  f2;

+};

+

+coherent buffer Buffer

+{

+    volatile float f1;

+    restrict vec2  f2;

+    readonly vec3  f3;

+    writeonly vec4 f4;

+    int i1;

+    Data data;

+};

+

+void main()

+{

+    vec4 texel = imageLoad(i1D, 1);

+    texel += imageLoad(i2D, ivec2(1));

+    texel += imageLoad(i2DRect, ivec2(1));

+    texel += imageLoad(i3D, ivec3(1));

+    imageStore(iCube, ivec3(1), texel);

+

+    texel[i1] = f1;

+    texel.xy += f2;

+    texel.xyz -= f3;

+    texel.w += data.f1 + data.f2[1];

+    f4 = texel;

+}
\ No newline at end of file
diff --git a/Test/test-spirv-list b/Test/test-spirv-list
index 51e2e8f..f22d500 100644
--- a/Test/test-spirv-list
+++ b/Test/test-spirv-list
@@ -60,6 +60,7 @@
 spv.matFun.vert
 spv.matrix.frag
 spv.matrix2.frag
+spv.memoryQualifier.frag
 spv.merge-unreachable.frag
 spv.newTexture.frag
 spv.nonSquare.vert