agpu_framebuffer *_agpu_framebuffer::create(agpu_device *device, agpu_uint width, agpu_uint height, agpu_uint colorCount, agpu_texture_view_description* colorViews, agpu_texture_view_description* depthStencilView) { agpu_framebuffer *result = nullptr; // Attachments std::vector<VkAttachmentDescription> attachments(colorCount + (depthStencilView != nullptr ? 1 : 0)); for (agpu_uint i = 0; i < colorCount; ++i) { auto view = &colorViews[i]; auto &attachment = attachments[i]; if (!view || !view->texture) return nullptr; attachment.format = mapTextureFormat(view->format); attachment.samples = VK_SAMPLE_COUNT_1_BIT; attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } if (depthStencilView != nullptr) { if (!depthStencilView->texture) return nullptr; auto &attachment = attachments.back(); attachment.format = mapTextureFormat(depthStencilView->format); attachment.samples = VK_SAMPLE_COUNT_1_BIT; attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } // Color reference std::vector<VkAttachmentReference> colorReference(colorCount); for (agpu_uint i = 0; i < colorCount; ++i) { colorReference[i].attachment = i; colorReference[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } // Depth reference VkAttachmentReference depthReference; memset(&depthReference, 0, sizeof(depthReference)); depthReference.attachment = colorCount; depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Sub pass VkSubpassDescription subpass; memset(&subpass, 0, sizeof(subpass)); subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = colorCount; subpass.pColorAttachments = &colorReference[0]; subpass.pDepthStencilAttachment = &depthReference; if (!depthStencilView) subpass.pDepthStencilAttachment = nullptr; // Render pass VkRenderPassCreateInfo renderPassCreateInfo; memset(&renderPassCreateInfo, 0, sizeof(renderPassCreateInfo)); renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassCreateInfo.attachmentCount = attachments.size(); renderPassCreateInfo.pAttachments = &attachments[0]; renderPassCreateInfo.subpassCount = 1; renderPassCreateInfo.pSubpasses = &subpass; VkRenderPass renderPass; auto error = vkCreateRenderPass(device->device, &renderPassCreateInfo, nullptr, &renderPass); if (error) return nullptr; // Create the framebuffer std::vector<VkImageView> attachmentViews(attachments.size()); for (agpu_uint i = 0; i < colorCount; ++i) { auto view = agpu_texture::createImageView(device, &colorViews[i]); if (!view) goto failure; attachmentViews[i] = view; } if (depthStencilView) { auto view = agpu_texture::createImageView(device, depthStencilView); if (!view) goto failure; attachmentViews.back() = view; } VkFramebufferCreateInfo createInfo; memset(&createInfo, 0, sizeof(createInfo)); createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; createInfo.attachmentCount = attachmentViews.size(); createInfo.pAttachments = &attachmentViews[0]; createInfo.renderPass = renderPass; createInfo.width = width; createInfo.height = height; createInfo.layers = 1; VkFramebuffer framebuffer; error = vkCreateFramebuffer(device->device, &createInfo, nullptr, &framebuffer); if (error) goto failure; result = new agpu_framebuffer(device); result->colorCount = colorCount; result->hasDepthStencil = depthStencilView != nullptr; result->width = width; result->height = height; result->renderPass = renderPass; result->framebuffer = framebuffer; result->attachmentViews = attachmentViews; result->attachmentTextures.resize(attachmentViews.size()); for (agpu_uint i = 0; i < colorCount; ++i) { auto texture = colorViews[i].texture; texture->retain(); result->attachmentTextures[i] = texture; } if (depthStencilView) { auto texture = depthStencilView->texture; texture->retain(); result->attachmentTextures.back() = texture; } return result; failure: vkDestroyRenderPass(device->device, renderPass, nullptr); for (auto view : attachmentViews) { if (view) vkDestroyImageView(device->device, view, nullptr); } return nullptr; }
int main(int /*argc*/, char ** /*argv*/) { try { vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); #if !defined(NDEBUG) vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); #endif std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(64, 64)); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())); vk::Format depthFormat = vk::Format::eD16Unorm; /* VULKAN_HPP_KEY_START */ vk::AttachmentDescription attachmentDescriptions[2]; attachmentDescriptions[0] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR); attachmentDescriptions[1] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), depthFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eDontCare, vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::AttachmentReference colorReference(0, vk::ImageLayout::eColorAttachmentOptimal); vk::AttachmentReference depthReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::SubpassDescription subpass(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr, 1, &colorReference, nullptr, &depthReference); vk::UniqueRenderPass renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpass)); // Note: No need to explicitly destroy the RenderPass or the Semaphore, as the corresponding destroy // functions are called by the destructor of the UniqueRenderPass and the UniqueSemaphore on leaving this scope. /* VULKAN_HPP_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif } catch (vk::SystemError err) { std::cout << "vk::SystemError: " << err.what() << std::endl; exit(-1); } catch (std::runtime_error err) { std::cout << "std::runtime_error: " << err.what() << std::endl; exit(-1); } catch (...) { std::cout << "unknown error\n"; exit(-1); } return 0; }