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