static VkAccessFlagBits getAccessMask(Resource::State state) { switch (state) { case Resource::State::Undefined: case Resource::State::Present: case Resource::State::Common: case Resource::State::PreInitialized: return VkAccessFlagBits(0); case Resource::State::VertexBuffer: return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; case Resource::State::ConstantBuffer: return VK_ACCESS_UNIFORM_READ_BIT; case Resource::State::IndexBuffer: return VK_ACCESS_INDEX_READ_BIT; case Resource::State::RenderTarget: return VkAccessFlagBits(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); case Resource::State::UnorderedAccess: return VK_ACCESS_SHADER_WRITE_BIT; case Resource::State::DepthStencil: return VkAccessFlagBits(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); case Resource::State::ShaderResource: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; case Resource::State::IndirectArg: return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; case Resource::State::CopyDest: return VK_ACCESS_TRANSFER_WRITE_BIT; case Resource::State::CopySource: return VK_ACCESS_TRANSFER_READ_BIT; case Resource::State::ResolveDest: return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; case Resource::State::ResolveSource: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; default: should_not_get_here(); return VkAccessFlagBits(-1); } }
bool _agpu_swap_chain::initialize(agpu_swap_chain_create_info *createInfo) { swapChainWidth = createInfo->width; swapChainHeight = createInfo->height; VkSurfaceCapabilitiesKHR surfaceCapabilities; auto error = device->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physicalDevice, surface, &surfaceCapabilities); if (error) return false; uint32_t presentModeCount; error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, nullptr); if (error) return false; std::vector<VkPresentModeKHR> presentModes(presentModeCount); error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, &presentModes[0]); if (error) return false; VkExtent2D swapchainExtent; if (surfaceCapabilities.currentExtent.width == (uint32_t)-1) { swapchainExtent.width = swapChainWidth; swapchainExtent.height = swapChainHeight; } else { swapchainExtent = surfaceCapabilities.currentExtent; swapChainWidth = swapchainExtent.width; swapChainHeight = swapchainExtent.height; } VkPresentModeKHR swapchainPresentMode = presentModes[0]; for (size_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_FIFO_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; } if (presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; break; } } uint32_t desiredNumberOfSwapchainImages = std::max(surfaceCapabilities.minImageCount, createInfo->buffer_count); if ((surfaceCapabilities.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfaceCapabilities.maxImageCount)) desiredNumberOfSwapchainImages = surfaceCapabilities.maxImageCount; VkSurfaceTransformFlagsKHR preTransform; if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfaceCapabilities.currentTransform; } VkSwapchainCreateInfoKHR swapchainInfo; memset(&swapchainInfo, 0, sizeof(swapchainInfo)); swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainInfo.surface = surface; swapchainInfo.minImageCount = desiredNumberOfSwapchainImages; swapchainInfo.imageFormat = format; swapchainInfo.imageColorSpace = colorSpace; swapchainInfo.imageExtent = swapchainExtent; swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; swapchainInfo.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainInfo.presentMode = swapchainPresentMode; swapchainInfo.oldSwapchain = handle; error = device->fpCreateSwapchainKHR(device->device, &swapchainInfo, nullptr, &handle); if (error) return false; error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, nullptr); if (error) return false; std::vector<VkImage> swapChainImages(imageCount); error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, &swapChainImages[0]); if (error) return false; // Color buffers descriptions agpu_texture_description colorDesc; memset(&colorDesc, 0, sizeof(colorDesc)); colorDesc.type = AGPU_TEXTURE_2D; colorDesc.width = createInfo->width; colorDesc.height = createInfo->height; colorDesc.depthOrArraySize = 1; colorDesc.format = agpuFormat; colorDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDER_TARGET | AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); colorDesc.miplevels = 1; colorDesc.sample_count = 1; // Depth stencil buffer descriptions. agpu_texture_description depthStencilDesc; memset(&depthStencilDesc, 0, sizeof(depthStencilDesc)); depthStencilDesc.type = AGPU_TEXTURE_2D; depthStencilDesc.width = createInfo->width; depthStencilDesc.height = createInfo->height; depthStencilDesc.depthOrArraySize = 1; depthStencilDesc.format = createInfo->depth_stencil_format; depthStencilDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); depthStencilDesc.miplevels = 1; bool hasDepth = hasDepthComponent(createInfo->depth_stencil_format); bool hasStencil = hasStencilComponent(createInfo->depth_stencil_format); if (hasDepth) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_DEPTH); if (hasStencil) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_STENCIL); agpu_texture_view_description colorViewDesc; agpu_texture_view_description depthStencilViewDesc; auto depthStencilViewPointer = &depthStencilViewDesc; if (!hasDepth && !hasStencil) depthStencilViewPointer = nullptr; // Create the semaphores VkSemaphoreCreateInfo semaphoreInfo; memset(&semaphoreInfo, 0, sizeof(semaphoreInfo)); semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphores.resize(imageCount, VK_NULL_HANDLE); currentSemaphoreIndex = 0; for (size_t i = 0; i < imageCount; ++i) { error = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &semaphores[i]); if(error) return false; } VkClearColorValue clearColor; memset(&clearColor, 0, sizeof(clearColor)); framebuffers.resize(imageCount); for (size_t i = 0; i < imageCount; ++i) { auto colorImage = swapChainImages[i]; VkImageSubresourceRange range; memset(&range, 0, sizeof(range)); range.layerCount = 1; range.levelCount = 1; if (!device->clearImageWithColor(colorImage, range, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VkAccessFlagBits(0), &clearColor)) return false; agpu_texture *colorBuffer = nullptr; agpu_texture *depthStencilBuffer = nullptr; { colorBuffer = agpu_texture::createFromImage(device, &colorDesc, colorImage); if (!colorBuffer) return false; // Get the color buffer view description. colorBuffer->getFullViewDescription(&colorViewDesc); } { depthStencilBuffer = agpu_texture::create(device, &depthStencilDesc); if (!depthStencilBuffer) { colorBuffer->release(); return false; } // Get the depth stencil buffer view description. depthStencilBuffer->getFullViewDescription(&depthStencilViewDesc); } auto framebuffer = agpu_framebuffer::create(device, swapChainWidth, swapChainHeight, 1, &colorViewDesc, depthStencilViewPointer); framebuffer->swapChainFramebuffer = true; framebuffers[i] = framebuffer; // Release the references to the buffers. colorBuffer->release(); depthStencilBuffer->release(); if (!framebuffer) return false; } if (!getNextBackBufferIndex()) return false; return true; }