-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathExtensions.cpp
138 lines (93 loc) · 5.82 KB
/
Extensions.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "test/Modules.h"
#include "spvgentwo/GLSL450Instruction.h"
#include "spvgentwo/Templates.h"
using namespace spvgentwo;
using namespace ext;
spvgentwo::Module test::extensions(spvgentwo::IAllocator* _pAllocator, spvgentwo::ILogger* _pLogger)
{
// create a new spir-v module
Module module(_pAllocator, spv::AddressingModel::Logical, spv::MemoryModel::VulkanKHR, _pLogger);
module.addCapability(spv::Capability::Shader);
module.addCapability(spv::Capability::Float64);
module.addCapability(spv::Capability::InterpolationFunction);
// use Vulkan Memory Model
module.addCapability(spv::Capability::VulkanMemoryModelKHR);
module.addExtension(u8"SPV_KHR_vulkan_memory_model"); // add extension by string
// Instruction* extId = module.getExtensionInstructionImport("GLSL.std.450");
// void entryPoint();
{
EntryPoint& entry = module.addEntryPoint(spv::ExecutionModel::Fragment, u8"main");
entry.addExecutionMode(spv::ExecutionMode::OriginUpperLeft);
BasicBlock& bb = *entry; // get entry block to this function
// SPV_AMD_gcn_shader example: https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/AMD/SPV_AMD_gcn_shader.html
{
module.addExtension(u8"SPV_AMD_gcn_shader"); // adds an OpExtension instruction to the module
// opcodes taken from extension spec:
const unsigned int CubeFaceCoordAMD = 2;
const unsigned int CubeFaceIndexAMD = 1;
const unsigned int TimeAMD = 3;
// getExtensionInstructionImport adds extension to the module
// return value ext can be used with Instruction.opExtInst(resultType, extId, opCode, ...);
Instruction* extId = module.addExtensionInstructionImport(u8"SPV_AMD_gcn_shader");
/// CubeFaceCoordAMD example:
// Result Type must be a 2-component 32-bit floating-point vector.
Instruction* vec2 = module.type<vector_t<float, 2>>();
// The operand <P> must be a pointer to a 3-component 32-bit floating-point vector.
Instruction* P = entry.variable<vector_t<float, 3>>();
// use extId generated by getExtensionInstructionImport (which adds OpExtInstImport)
Instruction* faceCoord = bb->opExtInst(vec2, extId, CubeFaceCoordAMD, P);
/// TimeAMD example:
//Use of this instruction requires declaration of the Int64 capability.
//Result Type must be a 64 - bit unsigned integer scalar.
Instruction* uint64 = module.type<unsigned long int>();
// The second variant of opExtInst can direclty add the extension to the module by supplying the extension name "GLSL.std.450"
Instruction* time = bb->opExtInst(uint64, u8"SPV_AMD_gcn_shader", TimeAMD);
}
// SpvGenTwo comes with GLSL extension instructions (GLSL450Intruction derives from Instruction>
Instruction* const vec3 = module.constant(make_vector(1.f, 2.f, 3.f));
// BasicBlock template function ext<T> adds a new Instruction and casts it to type T
// this works as long as T does not add any data members and just functionally extends the Instruction class
Instruction* const cross = bb.ext<GLSL450Intruction>()->opCross(vec3, vec3); // use GLSL.std.450 extension
// ext<T> is usefull for extension instruction derivates that are foreign to spvgentwo
// For GLSL 4.5 we have the glsl() and ext<GLSL>() shortcuts:
Instruction* const norm = bb.glsl()->opNormalize(cross);
Instruction* const ff = bb.ext<GLSL>()->opFaceForward(vec3, norm, cross);
Instruction* const refl = bb.glsl()->opReflect(vec3, norm);
Instruction* const eta = bb->opDot(refl, ff);
Instruction* const refr = bb.glsl()->opRefract(refl, ff, eta);
Instruction* const len = bb.glsl()->opLength(refr);
Instruction* const dist = bb.glsl()->opDistance(refl, refr);
Instruction* const modf = bb.glsl()->opModfStruct(refl);
Instruction* const frexp = bb.glsl()->opFrexpStruct(refr);
Instruction* const expInt = bb->opCompositeExtract(frexp, 1u); // extract the exponent
Instruction* const ldexp = bb.glsl()->opLdexp(ff, expInt);
Instruction* const vec4 = module.constant(make_vector(1.f, 2.f, 3.f, 4.f));
Instruction* const vec2 = module.constant(make_vector(1.f, 2.f));
Instruction* const ivec2 = module.constant(make_vector(1, 2));
Instruction* pack = bb.glsl()->opPackSnorm4x8(vec4);
bb.glsl()->opUnpackSnorm4x8(pack);
pack = bb.glsl()->opPackUnorm4x8(vec4);
bb.glsl()->opUnpackUnorm4x8(pack);
pack = bb.glsl()->opPackSnorm2x16(vec2);
bb.glsl()->opUnpackSnorm2x16(pack);
pack = bb.glsl()->opPackUnorm2x16(vec2);
bb.glsl()->opUnpackUnorm2x16(pack);
pack = bb.glsl()->opPackHalf2x16(vec2);
bb.glsl()->opUnpackHalf2x16(pack);
pack = bb.glsl()->opPackDouble2x32(ivec2);
bb.glsl()->opUnpackDouble2x32(pack);
Instruction* const ilsb = bb.glsl()->opFindILsb(ivec2);
Instruction* const smsb = bb.glsl()->opFindSMsb(ivec2);
Instruction* const umsm = bb.glsl()->opFindUMsb(ivec2);
Instruction* const inputVar = module.input<vector_t<float, 4>>("interpolant");
Instruction* const interpolant = bb->opAccessChain(inputVar, 0u);
Instruction* const ipolC = bb.glsl()->opInterpolateAtCentroid(interpolant);
Instruction* const ipolS = bb.glsl()->opInterpolateAtSample(interpolant, module.constant(2));
Instruction* const ipolO = bb.glsl()->opInterpolateAtOffset(interpolant, vec2);
bb.glsl()->opNMin(ipolC, ipolO);
bb.glsl()->opNMax(ipolS, ipolO);
bb.glsl()->opNClamp(ipolC, ipolO, ipolS);
entry->opReturn();
}
return module;
}