1 module gfx.graal.renderpass;
2 
3 import gfx.core.rc;
4 import gfx.core.typecons : Option;
5 import gfx.graal.cmd : Access, PipelineStage;
6 import gfx.graal.format;
7 import gfx.graal.image;
8 import gfx.graal.types;
9 
10 import std.math : isPowerOf2;
11 import std.typecons : Flag, Yes;
12 
13 /// Attachment load operation at the beginning of a render pass
14 enum LoadOp
15 {
16     /// the previous content of the image is preserved
17     load,
18     /// the content of the image is cleared
19     clear,
20     /// the content of the image is undefined
21     dontCare
22 }
23 
24 /// Attachment store operation at the end of a render pass
25 enum StoreOp
26 {
27     /// the content of the image is stored for later processing
28     store,
29     /// the content of the image is discarded
30     dontCare
31 }
32 
33 /// The operations performed on an attachment when it enters and leaves a render pass
34 struct AttachmentOps
35 {
36     LoadOp load;
37     StoreOp store;
38 }
39 
40 /// Describes an image attachment in a render pass or framebuffer
41 struct AttachmentDescription
42 {
43     /// the format of the attachment
44     Format format;
45     /// Sample count of the attachment
46     /// Must be a power of two between 1 and 64
47     uint samples = 1;
48     /// the operations to be performed on the attachment
49     /// color and depth attachments may only need to define the ops member
50     /// depth-stencil attachments must define both ops (for depth) and stencilOps members.
51     AttachmentOps ops = AttachmentOps(LoadOp.dontCare, StoreOp.dontCare);
52     /// ditto
53     AttachmentOps stencilOps = AttachmentOps(LoadOp.dontCare, StoreOp.dontCare);
54     /// The ImageLayout transition of the attachment.
55     /// layoutTrans.from is the initial layout of the attachment when it enters the render pass.
56     /// it is up to the programmer to ensure that the attachment will be in this state.
57     /// layoutTrans.to is the layout of the attachment when it exits the render pass.
58     Trans!ImageLayout layoutTrans;
59     /// Set mayAlias to Yes if a part of the attachment memory is shared with parts of other attachments
60     /// in the same render pass.
61     Flag!"mayAlias" mayAlias;
62 
63     /// Build a color attachment description
64     static AttachmentDescription color(Format format, AttachmentOps ops,
65             Trans!ImageLayout layoutTrans)
66     in(colorBits(format.formatDesc.surfaceType) > 0)
67     {
68         AttachmentDescription ad;
69         ad.format = format;
70         ad.ops = ops;
71         ad.layoutTrans = layoutTrans;
72         return ad;
73     }
74 
75     /// Build a depth attachment description
76     static AttachmentDescription depth(Format format, AttachmentOps ops,
77             Trans!ImageLayout layoutTrans)
78     in(depthBits(format.formatDesc.surfaceType) > 0)
79     {
80         AttachmentDescription ad;
81         ad.format = format;
82         ad.ops = ops;
83         ad.layoutTrans = layoutTrans;
84         return ad;
85     }
86 
87     /// Build a depth-stencil attachment description
88     static AttachmentDescription depthStencil(Format format, AttachmentOps depthOps,
89             AttachmentOps stencilOps, Trans!ImageLayout layoutTrans)
90     in(depthBits(format.formatDesc.surfaceType) > 0)
91     in(stencilBits(format.formatDesc.surfaceType) > 0)
92     {
93         AttachmentDescription ad;
94         ad.format = format;
95         ad.ops = depthOps;
96         ad.stencilOps = stencilOps;
97         ad.layoutTrans = layoutTrans;
98         return ad;
99     }
100 
101     /// Set samples to the description
102     AttachmentDescription withSamples(uint samples)
103     in(isPowerOf2(samples) && samples >= 1 && samples <= 64)
104     {
105         this.samples = samples;
106         return this;
107     }
108 
109     /// Set mayAlias to Yes
110     AttachmentDescription withMayAlias()
111     {
112         this.mayAlias = Yes.mayAlias;
113         return this;
114     }
115 }
116 
117 /// A reference to an attachment
118 struct AttachmentRef
119 {
120     /// The index of the attachment in the framebuffer
121     uint attachment;
122     /// The layout the attachment will be in the subpass this reference is used
123     ImageLayout layout;
124 }
125 
126 /// Decription of a subpass in a renderpass
127 struct SubpassDescription
128 {
129     /// Input attachments (read from in fragment shader)
130     AttachmentRef[] inputs;
131     /// Color-output attachments (written to in fragment shader)
132     AttachmentRef[] colors;
133     /// depth-stencil attachment (if any)
134     Option!AttachmentRef depthStencil;
135     /// Indices of attachments that are not used but whose content must be preserved
136     /// throughout the subpass
137     uint[] preserves;
138 }
139 
140 /// virtual subpass index for subpass dependencies that relates to what is before or after
141 /// the render pass
142 enum subpassExternal = uint.max;
143 
144 /// The SubpassDependency structure describes synchronization dependencies
145 /// between two subpasses in a render pass
146 struct SubpassDependency
147 {
148     /// subpass indices of the source and destination subpasses
149     Trans!uint subpass;
150     /// Pipeline stage masks of source and destination subpasses
151     Trans!PipelineStage stageMask;
152     /// Memory access masks of source and destination subpasses
153     Trans!Access accessMask;
154 }
155 
156 /// A render pass is a succession of one or more subpasses,
157 /// each of which describes what image attachments are used
158 /// and how they are laid out in memory.
159 interface RenderPass : IAtomicRefCounted
160 {
161     import gfx.graal.device : Device;
162 
163     /// Get the device that issued the render pass
164     @property Device device();
165 }
166 
167 /// Framebuffer is a collection of images attachments used
168 /// in a render pass.
169 /// When a render pass is started in a command buffer, a framebuffer
170 /// is tied to it so that its input and output attachments are used
171 /// during the rendering operations.
172 interface Framebuffer : IAtomicRefCounted
173 {
174     import gfx.graal.device : Device;
175 
176     /// Get the device that issued the framebuffer
177     @property Device device();
178 }