1 /// Image module
2 module gfx.graal.image;
3 
4 import gfx.core.rc;
5 import gfx.core.typecons;
6 import gfx.graal.format;
7 import gfx.graal.memory;
8 import gfx.graal.pipeline : CompareOp;
9 
10 import std.typecons : Flag;
11 
12 enum ImageType {
13     d1, d1Array,
14     d2, d2Array,
15     d3, cube, cubeArray
16 }
17 
18 bool isCube(in ImageType it) {
19     return it == ImageType.cube || it == ImageType.cubeArray;
20 }
21 
22 bool isArray(in ImageType it) {
23     return it == ImageType.d1Array || it == ImageType.d2Array || it == ImageType.cubeArray;
24 }
25 
26 enum CubeFace {
27     none,
28     posX, negX,
29     posY, negY,
30     posZ, negZ,
31 }
32 
33 /// an array of faces in the order that is expected during cube initialization
34 immutable cubeFaces = [
35     CubeFace.posX, CubeFace.negX,
36     CubeFace.posY, CubeFace.negY,
37     CubeFace.posZ, CubeFace.negZ,
38 ];
39 
40 struct ImageDims
41 {
42     uint width;
43     uint height;
44     uint depth;
45     uint layers;
46 
47     static ImageDims d1 (in uint width) {
48         return ImageDims(width, 1, 1, 1);
49     }
50     static ImageDims d2 (in uint width, in uint height) {
51         return ImageDims(width, height, 1, 1);
52     }
53     static ImageDims d3 (in uint width, in uint height, in uint depth) {
54         return ImageDims(width, height, depth, 1);
55     }
56     static ImageDims cube (in uint width, in uint height) {
57         return ImageDims(width, height, 6, 1);
58     }
59     static ImageDims d1Array (in uint width, in uint layers) {
60         return ImageDims(width, 1, 1, layers);
61     }
62     static ImageDims d2Array (in uint width, uint height, in uint layers) {
63         return ImageDims(width, height, 1, layers);
64     }
65     static ImageDims cubeArray (in uint width, in uint height, in uint layers) {
66         return ImageDims(width, height, 6, layers);
67     }
68 }
69 
70 enum ImageUsage {
71     none = 0,
72     transferSrc             = 0x01,
73     transferDst             = 0x02,
74     sampled                 = 0x04,
75     storage                 = 0x08,
76     colorAttachment         = 0x10,
77     depthStencilAttachment  = 0x20,
78     transientAttachment     = 0x40,
79     inputAttachment         = 0x80,
80 }
81 
82 enum ImageLayout {
83 	undefined                       = 0,
84 	general                         = 1,
85 	colorAttachmentOptimal          = 2,
86 	depthStencilAttachmentOptimal   = 3,
87 	depthStencilReadOnlyOptimal     = 4,
88 	shaderReadOnlyOptimal           = 5,
89 	transferSrcOptimal              = 6,
90 	transferDstOptimal              = 7,
91 	preinitialized                  = 8,
92     presentSrc                      = 1000001002, // TODO impl actual mapping to vulkan
93 }
94 
95 enum ImageAspect {
96     color           = 0x01,
97     depth           = 0x02,
98     stencil         = 0x04,
99     depthStencil    = depth | stencil,
100 }
101 
102 
103 struct ImageSubresourceRange
104 {
105     ImageAspect aspect;
106     size_t firstLevel;
107     size_t levels;
108     size_t firstLayer;
109     size_t layers;
110 }
111 
112 enum CompSwizzle : ubyte
113 {
114     identity,
115     zero, one,
116     r, g, b, a,
117 }
118 
119 alias Swizzle = CompSwizzle[4];
120 
121 interface Image
122 {
123     @property ImageType type();
124     @property Format format();
125     @property ImageDims dims();
126     @property uint levels();
127 
128     // TODO: deduce view type from subrange and image type
129     ImageView createView(ImageType viewtype, ImageSubresourceRange isr, Swizzle swizzle);
130 }
131 
132 interface ImageRc : Image, AtomicRefCounted
133 {
134     @property MemoryRequirements memoryRequirements();
135     /// The image keeps a reference of the device memory
136     void bindMemory(DeviceMemory mem, in size_t offset);
137 }
138 
139 interface ImageView : AtomicRefCounted
140 {
141     @property Image image();
142     @property ImageSubresourceRange subresourceRange();
143     @property Swizzle swizzle();
144 }
145 
146 
147 enum Filter {
148     nearest,
149     linear,
150 }
151 
152 
153 /// Specifies how texture coordinates outside the range `[0, 1]` are handled.
154 enum WrapMode {
155     /// Repeat the texture. That is, sample the coordinate modulo `1.0`.
156     repeat,
157     /// Mirror the texture. Like tile, but uses abs(coord) before the modulo.
158     mirrorRepeat,
159     /// Clamp the texture to the value at `0.0` or `1.0` respectively.
160     clamp,
161     /// Use border color.
162     border,
163 }
164 
165 enum BorderColor
166 {
167     floatTransparent,
168     intTransparent,
169     floatBlack,
170     intBlack,
171     floatWhite,
172     intWhite,
173 }
174 
175 ///
176 struct SamplerInfo {
177     Filter minFilter;
178     Filter magFilter;
179     Filter mipmapFilter;
180     WrapMode[3] wrapMode;
181     Option!float anisotropy;
182     float lodBias;
183     float[2] lodRange;
184     Option!CompareOp compare;
185     BorderColor borderColor;
186     Flag!"unnormalizeCoords" unnormalizeCoords;
187 
188     static @property SamplerInfo bilinear() {
189         SamplerInfo si;
190         si.minFilter = Filter.linear;
191         si.magFilter = Filter.linear;
192         return si;
193     }
194 
195     static @property SamplerInfo trilinear() {
196         SamplerInfo si;
197         si.minFilter = Filter.linear;
198         si.magFilter = Filter.linear;
199         si.mipmapFilter = Filter.linear;
200         return si;
201     }
202 }
203 
204 interface Sampler : AtomicRefCounted
205 {}