1 module gfx.gl3.conv; 2 3 package: 4 5 import gfx.bindings.opengl.gl; 6 import gfx.graal.buffer : BufferUsage, IndexType; 7 import gfx.graal.format : Format; 8 import gfx.graal.image : Filter, ImageType, WrapMode; 9 import gfx.graal.pipeline : CompareOp, FrontFace, PolygonMode, Primitive, 10 ShaderStage, StencilOp; 11 12 GLenum toGl(in BufferUsage usage) pure { 13 switch (usage) { 14 case BufferUsage.transferSrc: return GL_COPY_READ_BUFFER; 15 case BufferUsage.transferDst: return GL_COPY_WRITE_BUFFER; 16 case BufferUsage.uniform: return GL_UNIFORM_BUFFER; 17 case BufferUsage.index: return GL_ELEMENT_ARRAY_BUFFER; 18 case BufferUsage.vertex: return GL_ARRAY_BUFFER; 19 case BufferUsage.indirect: return GL_DRAW_INDIRECT_BUFFER; 20 default: return 0; 21 } 22 } 23 24 GLenum toGlTexTarget(in ImageType type, in bool ms) pure { 25 final switch (type) { 26 case ImageType.d1: return GL_TEXTURE_1D; 27 case ImageType.d1Array: return GL_TEXTURE_1D_ARRAY; 28 case ImageType.d2: 29 return ms ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; 30 case ImageType.d2Array: 31 return ms ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; 32 case ImageType.d3: return GL_TEXTURE_3D; 33 case ImageType.cube: return GL_TEXTURE_CUBE_MAP; 34 case ImageType.cubeArray: return GL_TEXTURE_CUBE_MAP_ARRAY; 35 } 36 } 37 38 GLenum toGlImgFmt(in Format graalFormat) pure { 39 switch (graalFormat) { 40 case Format.r8_uNorm: return GL_R8; 41 case Format.rg8_uNorm: return GL_RG8; 42 case Format.rgba8_uNorm: return GL_RGBA8; 43 case Format.r8_sInt: return GL_R8I; 44 case Format.rg8_sInt: return GL_RG8I; 45 case Format.rgba8_sInt: return GL_RGBA8I; 46 case Format.r8_uInt: return GL_R8UI; 47 case Format.rg8_uInt: return GL_RG8UI; 48 case Format.rgba8_uInt: return GL_RGBA8UI; 49 case Format.r16_uNorm: return GL_R16; 50 case Format.rg16_uNorm: return GL_RG16; 51 case Format.rgba16_uNorm: return GL_RGBA16; 52 case Format.r16_sInt: return GL_R16I; 53 case Format.rg16_sInt: return GL_RG16I; 54 case Format.rgba16_sInt: return GL_RGBA16I; 55 case Format.r16_uInt: return GL_R16UI; 56 case Format.rg16_uInt: return GL_RG16UI; 57 case Format.rgba16_uInt: return GL_RGBA16UI; 58 case Format.d16_uNorm: return GL_DEPTH_COMPONENT16; 59 case Format.x8d24_uNorm: return GL_DEPTH_COMPONENT24; 60 case Format.d32_sFloat: return GL_DEPTH_COMPONENT32F; 61 case Format.d24s8_uNorm: return GL_DEPTH24_STENCIL8; 62 case Format.s8_uInt: return GL_STENCIL_INDEX8; 63 default: 64 import std.format : format; 65 throw new Exception(format("Gfx-GL3: Format.%s is not supported.", graalFormat)); 66 } 67 } 68 69 GLenum toSubImgFmt(in Format graalFormat) pure { 70 switch(graalFormat) { 71 case Format.r8_uNorm: return GL_RED; 72 case Format.rg8_uNorm: return GL_RG; 73 case Format.rgba8_uNorm: return GL_RGBA; 74 case Format.r8_sInt: return GL_RED; 75 case Format.rg8_sInt: return GL_RG; 76 case Format.rgba8_sInt: return GL_RGBA; 77 case Format.r8_uInt: return GL_RED; 78 case Format.rg8_uInt: return GL_RG; 79 case Format.rgba8_uInt: return GL_RGBA; 80 case Format.r16_uNorm: return GL_RED; 81 case Format.rg16_uNorm: return GL_RG; 82 case Format.rgba16_uNorm: return GL_RGBA; 83 case Format.r16_sInt: return GL_RED; 84 case Format.rg16_sInt: return GL_RG; 85 case Format.rgba16_sInt: return GL_RGBA; 86 case Format.r16_uInt: return GL_RED; 87 case Format.rg16_uInt: return GL_RG; 88 case Format.rgba16_uInt: return GL_RGBA; 89 case Format.d16_uNorm: return GL_DEPTH_COMPONENT; 90 case Format.x8d24_uNorm: return GL_DEPTH_COMPONENT; 91 case Format.d32_sFloat: return GL_DEPTH_COMPONENT; 92 case Format.d24s8_uNorm: return GL_DEPTH_COMPONENT; 93 case Format.s8_uInt: return GL_STENCIL_INDEX; 94 default: 95 import std.format : format; 96 throw new Exception(format("Gfx-GL3: Format.%s is not supported.", graalFormat)); 97 } 98 } 99 100 GLenum toSubImgType(in Format graalFormat) pure { 101 switch(graalFormat) { 102 case Format.r8_uNorm: 103 case Format.rg8_uNorm: 104 case Format.rgba8_uNorm: 105 case Format.r8_sInt: 106 case Format.rg8_sInt: 107 case Format.rgba8_sInt: 108 case Format.r8_uInt: 109 case Format.rg8_uInt: 110 case Format.rgba8_uInt: 111 return GL_UNSIGNED_BYTE; 112 case Format.r16_uNorm: 113 case Format.rg16_uNorm: 114 case Format.rgba16_uNorm: 115 case Format.r16_sInt: 116 case Format.rg16_sInt: 117 case Format.rgba16_sInt: 118 case Format.r16_uInt: 119 case Format.rg16_uInt: 120 case Format.rgba16_uInt: 121 case Format.d16_uNorm: 122 return GL_UNSIGNED_SHORT; 123 case Format.x8d24_uNorm: 124 return GL_UNSIGNED_INT; 125 case Format.d32_sFloat: 126 return GL_FLOAT; 127 case Format.d24s8_uNorm: 128 return GL_UNSIGNED_INT; 129 case Format.s8_uInt: 130 return GL_UNSIGNED_BYTE; 131 default: 132 import std.format : format; 133 throw new Exception(format("Gfx-GL3: Format.%s is not supported.", graalFormat)); 134 } 135 } 136 137 GLenum toGlMag(in Filter filter) pure { 138 final switch(filter) { 139 case Filter.nearest: return GL_NEAREST; 140 case Filter.linear: return GL_LINEAR; 141 } 142 } 143 GLenum toGlMin(in Filter filter, in Filter mipmap) pure { 144 final switch(filter) { 145 case Filter.nearest: 146 final switch (mipmap) { 147 case Filter.nearest: return GL_NEAREST_MIPMAP_NEAREST; 148 case Filter.linear: return GL_NEAREST_MIPMAP_LINEAR; 149 } 150 case Filter.linear: 151 final switch (mipmap) { 152 case Filter.nearest: return GL_LINEAR_MIPMAP_NEAREST; 153 case Filter.linear: return GL_LINEAR_MIPMAP_LINEAR; 154 } 155 } 156 } 157 GLenum toGl(in WrapMode mode) pure { 158 final switch (mode) { 159 case WrapMode.repeat: return GL_REPEAT; 160 case WrapMode.mirrorRepeat: return GL_MIRRORED_REPEAT; 161 case WrapMode.clamp: return GL_CLAMP_TO_EDGE; 162 case WrapMode.border: return GL_CLAMP_TO_BORDER; 163 } 164 } 165 166 GLenum toGl(in CompareOp op) pure { 167 final switch (op) { 168 case CompareOp.never: return GL_NEVER; 169 case CompareOp.less: return GL_LESS; 170 case CompareOp.equal: return GL_EQUAL; 171 case CompareOp.lessOrEqual: return GL_LEQUAL; 172 case CompareOp.greater: return GL_GREATER; 173 case CompareOp.notEqual: return GL_NOTEQUAL; 174 case CompareOp.greaterOrEqual: return GL_GEQUAL; 175 case CompareOp.always: return GL_ALWAYS; 176 } 177 } 178 179 GLenum toGl(in StencilOp op) pure { 180 final switch (op) { 181 case StencilOp.keep: return GL_KEEP; 182 case StencilOp.zero: return GL_ZERO; 183 case StencilOp.replace: return GL_REPLACE; 184 case StencilOp.incrementAndClamp: return GL_INCR; 185 case StencilOp.decrementAndClamp: return GL_DECR; 186 case StencilOp.invert: return GL_INVERT; 187 case StencilOp.incrementAndWrap: return GL_INCR_WRAP; 188 case StencilOp.decrementAndWrap: return GL_DECR_WRAP; 189 } 190 } 191 192 GLenum toGl(in ShaderStage stage) pure { 193 switch (stage) { 194 case ShaderStage.vertex: return GL_VERTEX_SHADER; 195 case ShaderStage.tessellationControl: return GL_TESS_CONTROL_SHADER; 196 case ShaderStage.tessellationEvaluation: return GL_TESS_EVALUATION_SHADER; 197 case ShaderStage.geometry: return GL_GEOMETRY_SHADER; 198 case ShaderStage.fragment: return GL_FRAGMENT_SHADER; 199 case ShaderStage.compute: return GL_COMPUTE_SHADER; 200 default: assert(false); 201 } 202 } 203 204 GLenum toGl(in IndexType type) pure { 205 final switch (type) { 206 case IndexType.u16: return GL_UNSIGNED_SHORT; 207 case IndexType.u32: return GL_UNSIGNED_INT; 208 } 209 } 210 211 GLenum toGl(in Primitive primitive) pure { 212 final switch (primitive) { 213 case Primitive.pointList: return GL_POINTS; 214 case Primitive.lineList: return GL_LINES; 215 case Primitive.lineStrip: return GL_LINE_STRIP; 216 case Primitive.triangleList: return GL_TRIANGLES; 217 case Primitive.triangleStrip: return GL_TRIANGLE_STRIP; 218 case Primitive.triangleFan: return GL_TRIANGLE_FAN; 219 case Primitive.lineListAdjacency: return GL_LINES_ADJACENCY; 220 case Primitive.lineStripAdjacency: return GL_LINE_STRIP_ADJACENCY; 221 case Primitive.triangleListAdjacency: return GL_TRIANGLES_ADJACENCY; 222 case Primitive.triangleStripAdjacency: return GL_TRIANGLE_STRIP_ADJACENCY; 223 case Primitive.patchList: return GL_PATCHES; 224 } 225 } 226 227 GLenum toGl(in FrontFace ff) pure { 228 final switch (ff) { 229 case FrontFace.ccw: return GL_CCW; 230 case FrontFace.cw: return GL_CW; 231 } 232 } 233 234 GLenum toGl(in PolygonMode pm) pure { 235 final switch (pm) { 236 case PolygonMode.point: return GL_POINT; 237 case PolygonMode.line: return GL_LINE; 238 case PolygonMode.fill: return GL_FILL; 239 } 240 } 241 242 bool vertexFormatSupported(in Format f) pure { 243 import std.algorithm : canFind; 244 return supportedVertexFormats.canFind(f); 245 } 246 247 /// Specifies the function to define the VAO vertex attribs 248 enum VAOAttribFun { 249 /// glVertexAttribPointer 250 f, 251 /// glVertexAttribIPointer 252 i, 253 /// glVertexAttribLPointer 254 d 255 } 256 257 struct GlVertexFormat { 258 VAOAttribFun fun; 259 GLint size; 260 GLenum type; 261 GLboolean normalized; 262 } 263 264 GlVertexFormat glVertexFormat(in Format f) 265 in { 266 assert(vertexFormatSupported(f)); 267 } 268 body { 269 return glVertexFormats[cast(size_t)f]; 270 } 271 272 private: 273 274 // TODO: support more formats (unorms, integer...) 275 276 immutable(GlVertexFormat[]) glVertexFormats; 277 278 immutable(Format[]) supportedVertexFormats = [ 279 Format.r32_sFloat, 280 Format.rg32_sFloat, 281 Format.rgb32_sFloat, 282 Format.rgba32_sFloat, 283 ]; 284 285 shared static this() { 286 import gfx.graal.format : formatDesc, numComponents; 287 import std.algorithm : map, maxElement; 288 import std.exception : assumeUnique; 289 290 const len = 1 + supportedVertexFormats 291 .map!(f => cast(int)f) 292 .maxElement; 293 auto vertexFormats = new GlVertexFormat[len]; 294 foreach (f; supportedVertexFormats) { 295 const fd = formatDesc(f); 296 const size = numComponents(fd.surfaceType); 297 vertexFormats[cast(int)f] = GlVertexFormat( 298 VAOAttribFun.f, size, GL_FLOAT, GL_FALSE 299 ); 300 } 301 302 glVertexFormats = assumeUnique(vertexFormats); 303 }