void CTexture9::Clear(const vk::ClearDepthStencilValue& clearValue) { vk::ImageLayout originalLayout = mImageLayout; mDevice->BeginRecordingUtilityCommands(); { SetImageLayout(vk::ImageLayout::eTransferDstOptimal); const vk::ImageSubresourceRange subResourceRange = vk::ImageSubresourceRange() .setBaseMipLevel(0) .setLevelCount(1) .setBaseArrayLayer(0) .setLayerCount(1) .setAspectMask(vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil); mDevice->mCurrentUtilityCommandBuffer.clearDepthStencilImage(mImage.get(), vk::ImageLayout::eTransferDstOptimal, &clearValue, 1, &subResourceRange); SetImageLayout(originalLayout); } mDevice->StopRecordingUtilityCommands(); }
CTexture9::CTexture9(CDevice9* device, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, HANDLE *pSharedHandle) : mDevice(device), mWidth(Width), mHeight(Height), mLevels(Levels), mUsage(Usage), mFormat(Format), mPool(Pool), mSharedHandle(pSharedHandle) { Log(info) << "CTexture9::CTexture9" << std::endl; //mDevice->AddRef(); if (!mLevels) { mLevels = (UINT)std::log2(std::max(mWidth, mHeight)) + 1; } if (mUsage == 0) { mUsage = D3DUSAGE_RENDERTARGET; } mSurfaces.reserve(mLevels); UINT width = mWidth, height = mHeight; for (int32_t i = 0; i < (int32_t)mLevels; i++) { CSurface9* ptr = new CSurface9(mDevice, this, width, height, mUsage, 1 /*Levels*/, mFormat, D3DMULTISAMPLE_NONE, 0 /*MultisampleQuality*/, false /*Discard*/, false /*Lockable*/, mPool, mSharedHandle); ptr->mMipIndex = i; mSurfaces.push_back(ptr); width /= 2; height /= 2; if (height == 0) { height = 1; } if (width == 0 && Width > 0) { width = 1; } } const vk::ImageTiling tiling = vk::ImageTiling::eOptimal; const vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; const vk::MemoryPropertyFlags required_props = vk::MemoryPropertyFlagBits::eDeviceLocal; const vk::ImageCreateInfo imageCreateInfo = vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setFormat(ConvertFormat(mFormat)) .setExtent({ mWidth, mHeight, 1 }) .setMipLevels(mLevels) .setArrayLayers(1) .setSamples(vk::SampleCountFlagBits::e1) .setTiling(tiling) .setUsage(usage) .setSharingMode(vk::SharingMode::eExclusive) .setQueueFamilyIndexCount(0) .setPQueueFamilyIndices(nullptr) .setInitialLayout(vk::ImageLayout::ePreinitialized); mImage = mDevice->mDevice->createImageUnique(imageCreateInfo); vk::MemoryRequirements memoryRequirements; mDevice->mDevice->getImageMemoryRequirements(mImage.get(), &memoryRequirements); mImageMemoryAllocateInfo.setAllocationSize(memoryRequirements.size); mImageMemoryAllocateInfo.setMemoryTypeIndex(0); auto pass = mDevice->FindMemoryTypeFromProperties(memoryRequirements.memoryTypeBits, required_props, &mImageMemoryAllocateInfo.memoryTypeIndex); mImageDeviceMemory = mDevice->mDevice->allocateMemoryUnique(mImageMemoryAllocateInfo); mDevice->mDevice->bindImageMemory(mImage.get(), mImageDeviceMemory.get(), 0); //Now transition this thing from init to shader ready. SetImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal); /* This block handles the luminance & x formats. They are converted to color formats but need a little mapping to make them work correctly. */ vk::ComponentMapping componentMapping; switch (mFormat) { case D3DFMT_R5G6B5: //Vulkan has a matching format but nvidia doesn't support using it as a color attachment so we just use the other one and re-map the components. componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne); break; case D3DFMT_A8: //TODO: Revisit A8 mapping. componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eR); break; case D3DFMT_L8: componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne); break; case D3DFMT_L16: componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne); break; case D3DFMT_A8L8: componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG); break; case D3DFMT_X8R8G8B8: case D3DFMT_X8B8G8R8: componentMapping = vk::ComponentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eOne); break; default: break; } auto const viewInfo = vk::ImageViewCreateInfo() .setImage(mImage.get()) .setViewType(vk::ImageViewType::e2D) .setFormat(ConvertFormat(mFormat)) .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, mLevels, 0, 1)) .setComponents(componentMapping); mImageView = mDevice->mDevice->createImageViewUnique(viewInfo); }
void NewSwapchainInfo(WindowInfo* windowInfo, const PhysDeviceInfo* physDeviceInfo, const SurfaceInfo* surfaceInfo, const DeviceInfo* deviceInfo, SwapchainInfo* swapchainInfo) { //TODO parts of this function could be moved to other functions to improve the flow of initialization? //specifically move the use of the function extensions into a single function? VkResult error; //after logical device creation we can retrieve function pointers associated with it GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, CreateSwapchainKHR); GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, DestroySwapchainKHR); GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, GetSwapchainImagesKHR); GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, AcquireNextImageKHR); GET_VULKAN_FUNCTION_POINTER_DEV(deviceInfo->device, QueuePresentKHR); VkSurfaceCapabilitiesKHR surfaceCaps = GetSurfaceCaps(physDeviceInfo->physicalDevice, surfaceInfo->surface); std::vector<VkPresentModeKHR> presentModes = GetPresentModes(physDeviceInfo->physicalDevice, surfaceInfo->surface); VkSwapchainCreateInfoKHR scInfo = {}; scInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; scInfo.surface = surfaceInfo->surface; scInfo.minImageCount = GetDesiredNumSwapChainImages(&surfaceCaps); scInfo.imageFormat = surfaceInfo->colorFormat; scInfo.imageColorSpace = surfaceInfo->colorSpace; scInfo.imageExtent = GetSurfaceExtent(&surfaceCaps, &windowInfo->clientWidth, &windowInfo->clientHeight); scInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; scInfo.preTransform = GetSurfaceTransformBits(&surfaceCaps); scInfo.imageArrayLayers = 1; scInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; scInfo.presentMode = GetPresentMode(&presentModes); //TODO do I ever have an old swapchain and need to create a new one? //swapchainCI.oldSwapchain = oldSwapChain; scInfo.clipped = VK_TRUE; scInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; error = CreateSwapchainKHR(deviceInfo->device, &scInfo, nullptr, &swapchainInfo->swapChain); Assert(error, "could not create a swapchain"); error = GetSwapchainImagesKHR(deviceInfo->device, swapchainInfo->swapChain, &swapchainInfo->imageCount, nullptr); Assert(error, "could not get surface image count"); swapchainInfo->images.resize(swapchainInfo->imageCount); swapchainInfo->views.resize(swapchainInfo->imageCount); error = GetSwapchainImagesKHR(deviceInfo->device, swapchainInfo->swapChain, &swapchainInfo->imageCount, swapchainInfo->images.data()); Assert(error, "could not fill surface images vector"); for (uint32_t i = 0; i < swapchainInfo->imageCount; i++) { VkImageViewCreateInfo ivInfo = {}; ivInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; ivInfo.format = surfaceInfo->colorFormat; ivInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; ivInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ivInfo.subresourceRange.baseMipLevel = 0; ivInfo.subresourceRange.levelCount = 1; ivInfo.subresourceRange.baseArrayLayer = 0; ivInfo.subresourceRange.layerCount = 1; ivInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; ivInfo.flags = 0; SetImageLayout(deviceInfo->setupCmdBuffer, swapchainInfo->images[i], VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); ivInfo.image = swapchainInfo->images[i]; error = vkCreateImageView(deviceInfo->device, &ivInfo, nullptr, &swapchainInfo->views[i]); Assert(error, "could not create image view"); } }
void DrawScene() { // 次のバックバッファを取得する uint32_t currentBuffer = g_VkSwapchain.AcquireNextImage(g_VkPresentComplete); // コマンドバッファの積み込み { auto& cmdBuffer = g_VkCmdBuffers[currentBuffer]; cmdBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources); vk::CommandBufferBeginInfo cmdBufInfo; cmdBuffer.begin(cmdBufInfo); vk::ClearColorValue clearColor(std::array<float, 4>{ 0.0f, 0.0f, 0.5f, 1.0f }); // カラーバッファクリア { MySwapchain::Image& colorImage = g_VkSwapchain.GetImages()[currentBuffer]; vk::ImageSubresourceRange subresourceRange; subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; subresourceRange.levelCount = 1; subresourceRange.layerCount = 1; // カラーバッファクリアのため、レイアウトを変更する SetImageLayout( cmdBuffer, colorImage.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, subresourceRange); // クリアコマンド cmdBuffer.clearColorImage(colorImage.image, vk::ImageLayout::eTransferDstOptimal, clearColor, subresourceRange); // Presentのため、レイアウトを変更する SetImageLayout( cmdBuffer, colorImage.image, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::ePresentSrcKHR, subresourceRange); } cmdBuffer.end(); } // Submit { vk::PipelineStageFlags pipelineStages = vk::PipelineStageFlagBits::eBottomOfPipe; vk::SubmitInfo submitInfo; submitInfo.pWaitDstStageMask = &pipelineStages; // 待つ必要があるセマフォの数とその配列を渡す submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &g_VkPresentComplete; // Submitするコマンドバッファの配列を渡す // 複数のコマンドバッファをSubmitしたい場合は配列にする submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &g_VkCmdBuffers[currentBuffer]; // 描画完了を知らせるセマフォを登録する submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &g_VkRenderComplete; // Queueに対してSubmitする vk::Fence fence = g_VkSwapchain.GetSubmitFence(true); g_VkQueue.submit(submitInfo, fence); vk::Result fenceRes = g_VkDevice.waitForFences(fence, VK_TRUE, kFenceTimeout); assert(fenceRes == vk::Result::eSuccess); //g_VkQueue.waitIdle(); } // Present g_VkSwapchain.Present(g_VkRenderComplete); }