1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "fullscreen_color.h"
16
17 namespace cuttlefish {
18 namespace {
19
20 #include "fullscreen_color.frag.inl"
21 #include "fullscreen_color.vert.inl"
22
23 } // namespace
24
BuildVulkanSampleApp()25 Result<std::unique_ptr<SampleBase>> BuildVulkanSampleApp() {
26 return FullscreenColor::Create();
27 }
28
29 /*static*/
Create()30 Result<std::unique_ptr<SampleBase>> FullscreenColor::Create() {
31 std::unique_ptr<SampleBase> sample(new FullscreenColor());
32 VK_EXPECT(sample->StartUp());
33 return sample;
34 }
35
StartUp()36 Result<Ok> FullscreenColor::StartUp() {
37 VK_EXPECT(StartUpBase());
38
39 const vkhpp::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
40 .setLayoutCount = 0,
41 };
42 mPipelineLayout = VK_EXPECT_RV(
43 mDevice->createPipelineLayoutUnique(pipelineLayoutCreateInfo));
44
45 const vkhpp::ShaderModuleCreateInfo vertShaderCreateInfo = {
46 .codeSize = static_cast<uint32_t>(kFullscreenColorVert.size()),
47 .pCode = reinterpret_cast<const uint32_t*>(kFullscreenColorVert.data()),
48 };
49 mVertShaderModule =
50 VK_EXPECT_RV(mDevice->createShaderModuleUnique(vertShaderCreateInfo));
51
52 const vkhpp::ShaderModuleCreateInfo fragShaderCreateInfo = {
53 .codeSize = static_cast<uint32_t>(kFullscreenColorFrag.size()),
54 .pCode = reinterpret_cast<const uint32_t*>(kFullscreenColorFrag.data()),
55 };
56 mFragShaderModule =
57 VK_EXPECT_RV(mDevice->createShaderModuleUnique(fragShaderCreateInfo));
58
59 return Ok{};
60 }
61
CleanUp()62 Result<Ok> FullscreenColor::CleanUp() {
63 VK_EXPECT(CleanUpBase());
64
65 mDevice->waitIdle();
66
67 return Ok{};
68 }
69
CreateSwapchainDependents(const SwapchainInfo & swapchainInfo)70 Result<Ok> FullscreenColor::CreateSwapchainDependents(
71 const SwapchainInfo& swapchainInfo) {
72 const std::vector<vkhpp::AttachmentDescription> renderpassAttachments = {
73 {
74 .format = swapchainInfo.swapchainFormat,
75 .samples = vkhpp::SampleCountFlagBits::e1,
76 .loadOp = vkhpp::AttachmentLoadOp::eClear,
77 .storeOp = vkhpp::AttachmentStoreOp::eStore,
78 .stencilLoadOp = vkhpp::AttachmentLoadOp::eClear,
79 .stencilStoreOp = vkhpp::AttachmentStoreOp::eStore,
80 .initialLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
81 .finalLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
82 },
83 };
84 const vkhpp::AttachmentReference renderpassColorAttachmentRef = {
85 .attachment = 0,
86 .layout = vkhpp::ImageLayout::eColorAttachmentOptimal,
87 };
88 const vkhpp::SubpassDescription renderpassSubpass = {
89 .pipelineBindPoint = vkhpp::PipelineBindPoint::eGraphics,
90 .inputAttachmentCount = 0,
91 .pInputAttachments = nullptr,
92 .colorAttachmentCount = 1,
93 .pColorAttachments = &renderpassColorAttachmentRef,
94 .pResolveAttachments = nullptr,
95 .pDepthStencilAttachment = nullptr,
96 .pPreserveAttachments = nullptr,
97 };
98 const vkhpp::SubpassDependency renderpassSubpassDependency = {
99 .srcSubpass = VK_SUBPASS_EXTERNAL,
100 .dstSubpass = 0,
101 .srcStageMask = vkhpp::PipelineStageFlagBits::eColorAttachmentOutput,
102 .srcAccessMask = {},
103 .dstStageMask = vkhpp::PipelineStageFlagBits::eColorAttachmentOutput,
104 .dstAccessMask = vkhpp::AccessFlagBits::eColorAttachmentWrite,
105 };
106 const vkhpp::RenderPassCreateInfo renderpassCreateInfo = {
107 .attachmentCount = static_cast<uint32_t>(renderpassAttachments.size()),
108 .pAttachments = renderpassAttachments.data(),
109 .subpassCount = 1,
110 .pSubpasses = &renderpassSubpass,
111 .dependencyCount = 1,
112 .pDependencies = &renderpassSubpassDependency,
113 };
114 mRenderpass =
115 VK_EXPECT_RV(mDevice->createRenderPassUnique(renderpassCreateInfo));
116
117 for (const auto imageView : swapchainInfo.swapchainImageViews) {
118 const std::vector<vkhpp::ImageView> framebufferAttachments = {
119 imageView,
120 };
121 const vkhpp::FramebufferCreateInfo framebufferCreateInfo = {
122 .renderPass = *mRenderpass,
123 .attachmentCount = static_cast<uint32_t>(framebufferAttachments.size()),
124 .pAttachments = framebufferAttachments.data(),
125 .width = swapchainInfo.swapchainExtent.width,
126 .height = swapchainInfo.swapchainExtent.height,
127 .layers = 1,
128 };
129 auto framebuffer =
130 VK_EXPECT_RV(mDevice->createFramebufferUnique(framebufferCreateInfo));
131 mSwapchainImageObjects.push_back(SwapchainImageObjects{
132 .extent = swapchainInfo.swapchainExtent,
133 .framebuffer = std::move(framebuffer),
134 });
135 }
136
137 const std::vector<vkhpp::PipelineShaderStageCreateInfo> pipelineStages = {
138 vkhpp::PipelineShaderStageCreateInfo{
139 .stage = vkhpp::ShaderStageFlagBits::eVertex,
140 .module = *mVertShaderModule,
141 .pName = "main",
142 },
143 vkhpp::PipelineShaderStageCreateInfo{
144 .stage = vkhpp::ShaderStageFlagBits::eFragment,
145 .module = *mFragShaderModule,
146 .pName = "main",
147 },
148 };
149
150 const vkhpp::PipelineVertexInputStateCreateInfo
151 pipelineVertexInputStateCreateInfo = {};
152 const vkhpp::PipelineInputAssemblyStateCreateInfo
153 pipelineInputAssemblyStateCreateInfo = {
154 .topology = vkhpp::PrimitiveTopology::eTriangleStrip,
155 };
156 const vkhpp::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo =
157 {
158 .viewportCount = 1,
159 .pViewports = nullptr,
160 .scissorCount = 1,
161 .pScissors = nullptr,
162 };
163 const vkhpp::PipelineRasterizationStateCreateInfo
164 pipelineRasterStateCreateInfo = {
165 .depthClampEnable = VK_FALSE,
166 .rasterizerDiscardEnable = VK_FALSE,
167 .polygonMode = vkhpp::PolygonMode::eFill,
168 .cullMode = {},
169 .frontFace = vkhpp::FrontFace::eCounterClockwise,
170 .depthBiasEnable = VK_FALSE,
171 .depthBiasConstantFactor = 0.0f,
172 .depthBiasClamp = 0.0f,
173 .depthBiasSlopeFactor = 0.0f,
174 .lineWidth = 1.0f,
175 };
176 const vkhpp::SampleMask pipelineSampleMask = 65535;
177 const vkhpp::PipelineMultisampleStateCreateInfo
178 pipelineMultisampleStateCreateInfo = {
179 .rasterizationSamples = vkhpp::SampleCountFlagBits::e1,
180 .sampleShadingEnable = VK_FALSE,
181 .minSampleShading = 1.0f,
182 .pSampleMask = &pipelineSampleMask,
183 .alphaToCoverageEnable = VK_FALSE,
184 .alphaToOneEnable = VK_FALSE,
185 };
186 const vkhpp::PipelineDepthStencilStateCreateInfo
187 pipelineDepthStencilStateCreateInfo = {
188 .depthTestEnable = VK_FALSE,
189 .depthWriteEnable = VK_FALSE,
190 .depthCompareOp = vkhpp::CompareOp::eLess,
191 .depthBoundsTestEnable = VK_FALSE,
192 .stencilTestEnable = VK_FALSE,
193 .front =
194 {
195 .failOp = vkhpp::StencilOp::eKeep,
196 .passOp = vkhpp::StencilOp::eKeep,
197 .depthFailOp = vkhpp::StencilOp::eKeep,
198 .compareOp = vkhpp::CompareOp::eAlways,
199 .compareMask = 0,
200 .writeMask = 0,
201 .reference = 0,
202 },
203 .back =
204 {
205 .failOp = vkhpp::StencilOp::eKeep,
206 .passOp = vkhpp::StencilOp::eKeep,
207 .depthFailOp = vkhpp::StencilOp::eKeep,
208 .compareOp = vkhpp::CompareOp::eAlways,
209 .compareMask = 0,
210 .writeMask = 0,
211 .reference = 0,
212 },
213 .minDepthBounds = 0.0f,
214 .maxDepthBounds = 0.0f,
215 };
216 const std::vector<vkhpp::PipelineColorBlendAttachmentState>
217 pipelineColorBlendAttachments = {
218 vkhpp::PipelineColorBlendAttachmentState{
219 .blendEnable = VK_FALSE,
220 .srcColorBlendFactor = vkhpp::BlendFactor::eOne,
221 .dstColorBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
222 .colorBlendOp = vkhpp::BlendOp::eAdd,
223 .srcAlphaBlendFactor = vkhpp::BlendFactor::eOne,
224 .dstAlphaBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
225 .alphaBlendOp = vkhpp::BlendOp::eAdd,
226 .colorWriteMask = vkhpp::ColorComponentFlagBits::eR |
227 vkhpp::ColorComponentFlagBits::eG |
228 vkhpp::ColorComponentFlagBits::eB |
229 vkhpp::ColorComponentFlagBits::eA,
230 },
231 };
232 const vkhpp::PipelineColorBlendStateCreateInfo
233 pipelineColorBlendStateCreateInfo = {
234 .logicOpEnable = VK_FALSE,
235 .logicOp = vkhpp::LogicOp::eCopy,
236 .attachmentCount =
237 static_cast<uint32_t>(pipelineColorBlendAttachments.size()),
238 .pAttachments = pipelineColorBlendAttachments.data(),
239 .blendConstants = {{
240 0.0f,
241 0.0f,
242 0.0f,
243 0.0f,
244 }},
245 };
246 const std::vector<vkhpp::DynamicState> pipelineDynamicStates = {
247 vkhpp::DynamicState::eViewport,
248 vkhpp::DynamicState::eScissor,
249 };
250 const vkhpp::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {
251 .dynamicStateCount = static_cast<uint32_t>(pipelineDynamicStates.size()),
252 .pDynamicStates = pipelineDynamicStates.data(),
253 };
254 const vkhpp::GraphicsPipelineCreateInfo pipelineCreateInfo = {
255 .stageCount = static_cast<uint32_t>(pipelineStages.size()),
256 .pStages = pipelineStages.data(),
257 .pVertexInputState = &pipelineVertexInputStateCreateInfo,
258 .pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo,
259 .pTessellationState = nullptr,
260 .pViewportState = &pipelineViewportStateCreateInfo,
261 .pRasterizationState = &pipelineRasterStateCreateInfo,
262 .pMultisampleState = &pipelineMultisampleStateCreateInfo,
263 .pDepthStencilState = &pipelineDepthStencilStateCreateInfo,
264 .pColorBlendState = &pipelineColorBlendStateCreateInfo,
265 .pDynamicState = &pipelineDynamicStateCreateInfo,
266 .layout = *mPipelineLayout,
267 .renderPass = *mRenderpass,
268 .subpass = 0,
269 .basePipelineHandle = VK_NULL_HANDLE,
270 .basePipelineIndex = 0,
271 };
272 mPipeline = VK_EXPECT_RV(
273 mDevice->createGraphicsPipelineUnique({}, pipelineCreateInfo));
274
275 return Ok{};
276 }
277
DestroySwapchainDependents()278 Result<Ok> FullscreenColor::DestroySwapchainDependents() {
279 mPipeline.reset();
280 mSwapchainImageObjects.clear();
281 mRenderpass.reset();
282 return Ok{};
283 }
284
RecordFrame(const FrameInfo & frame)285 Result<Ok> FullscreenColor::RecordFrame(const FrameInfo& frame) {
286 vkhpp::CommandBuffer commandBuffer = frame.commandBuffer;
287
288 const SwapchainImageObjects& swapchainObjects =
289 mSwapchainImageObjects[frame.swapchainImageIndex];
290
291 const std::vector<vkhpp::ClearValue> renderPassBeginClearValues = {
292 vkhpp::ClearValue{
293 .color =
294 {
295 .float32 = {{1.0f, 0.0f, 0.0f, 1.0f}},
296 },
297 },
298 };
299 const vkhpp::RenderPassBeginInfo renderPassBeginInfo = {
300 .renderPass = *mRenderpass,
301 .framebuffer = *swapchainObjects.framebuffer,
302 .renderArea =
303 {
304 .offset =
305 {
306 .x = 0,
307 .y = 0,
308 },
309 .extent = swapchainObjects.extent,
310 },
311 .clearValueCount =
312 static_cast<uint32_t>(renderPassBeginClearValues.size()),
313 .pClearValues = renderPassBeginClearValues.data(),
314 };
315 commandBuffer.beginRenderPass(renderPassBeginInfo,
316 vkhpp::SubpassContents::eInline);
317
318 commandBuffer.bindPipeline(vkhpp::PipelineBindPoint::eGraphics, *mPipeline);
319
320 const vkhpp::Viewport viewport = {
321 .x = 0.0f,
322 .y = 0.0f,
323 .width = static_cast<float>(swapchainObjects.extent.width),
324 .height = static_cast<float>(swapchainObjects.extent.height),
325 .minDepth = 0.0f,
326 .maxDepth = 1.0f,
327 };
328 commandBuffer.setViewport(0, {viewport});
329
330 const vkhpp::Rect2D scissor = {
331 .offset =
332 {
333 .x = 0,
334 .y = 0,
335 },
336 .extent = swapchainObjects.extent,
337 };
338 commandBuffer.setScissor(0, {scissor});
339
340 commandBuffer.draw(4, 1, 0, 0);
341
342 commandBuffer.endRenderPass();
343
344 return Ok{};
345 }
346
347 } // namespace cuttlefish
348