void CommandBuffers::cmdClearDepthStencilImage(const VkImage image, const VkImageLayout imageLayout, const VkClearDepthStencilValue* depthStencil, const uint32_t rangeCount, const VkImageSubresourceRange* ranges, const uint32_t bufferIndex) const { vkCmdClearDepthStencilImage(allCommandBuffers[bufferIndex], image, imageLayout, depthStencil, rangeCount, ranges); }
bool FramebufferManager::CreateEFBFramebuffer() { m_efb_width = static_cast<u32>(std::max(Renderer::GetTargetWidth(), 1)); m_efb_height = static_cast<u32>(std::max(Renderer::GetTargetHeight(), 1)); m_efb_layers = (g_ActiveConfig.iStereoMode != STEREO_OFF) ? 2 : 1; INFO_LOG(VIDEO, "EFB size: %ux%ux%u", m_efb_width, m_efb_height, m_efb_layers); // Update the static variable in the base class. Why does this even exist? FramebufferManagerBase::m_EFBLayers = m_efb_layers; // Allocate EFB render targets m_efb_color_texture = Texture2D::Create(m_efb_width, m_efb_height, 1, m_efb_layers, EFB_COLOR_TEXTURE_FORMAT, m_efb_samples, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); // We need a second texture to swap with for changing pixel formats m_efb_convert_color_texture = Texture2D::Create(m_efb_width, m_efb_height, 1, m_efb_layers, EFB_COLOR_TEXTURE_FORMAT, m_efb_samples, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); m_efb_depth_texture = Texture2D::Create( m_efb_width, m_efb_height, 1, m_efb_layers, EFB_DEPTH_TEXTURE_FORMAT, m_efb_samples, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); if (!m_efb_color_texture || !m_efb_convert_color_texture || !m_efb_depth_texture) return false; // Create resolved textures if MSAA is on if (m_efb_samples != VK_SAMPLE_COUNT_1_BIT) { m_efb_resolve_color_texture = Texture2D::Create( m_efb_width, m_efb_height, 1, m_efb_layers, EFB_COLOR_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); m_efb_resolve_depth_texture = Texture2D::Create( m_efb_width, m_efb_height, 1, m_efb_layers, EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); if (!m_efb_resolve_color_texture || !m_efb_resolve_depth_texture) return false; VkImageView attachment = m_efb_resolve_depth_texture->GetView(); VkFramebufferCreateInfo framebuffer_info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, m_depth_resolve_render_pass, 1, &attachment, m_efb_width, m_efb_height, m_efb_layers }; VkResult res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &m_depth_resolve_framebuffer); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: "); return false; } } VkImageView framebuffer_attachments[] = { m_efb_color_texture->GetView(), m_efb_depth_texture->GetView(), }; VkFramebufferCreateInfo framebuffer_info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, m_efb_load_render_pass, static_cast<u32>(ArraySize(framebuffer_attachments)), framebuffer_attachments, m_efb_width, m_efb_height, m_efb_layers }; VkResult res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &m_efb_framebuffer); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: "); return false; } // Create second framebuffer for format conversions framebuffer_attachments[0] = m_efb_convert_color_texture->GetView(); res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &m_efb_convert_framebuffer); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: "); return false; } // Transition to state that can be used to clear m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Clear the contents of the buffers. static const VkClearColorValue clear_color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; static const VkClearDepthStencilValue clear_depth = { 0.0f, 0 }; VkImageSubresourceRange clear_color_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, m_efb_layers }; VkImageSubresourceRange clear_depth_range = { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, m_efb_layers }; vkCmdClearColorImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_color_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &clear_color_range); vkCmdClearDepthStencilImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_depth_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_depth, 1, &clear_depth_range); // Transition to color attachment state ready for rendering. m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); return true; }
//============================================================================== // 描画 //============================================================================== void Render() { VkResult result; VkCommandBuffer command = g_commandBuffers[g_currentBufferIndex]; //================================================== // コマンド記録開始 //================================================== VkCommandBufferInheritanceInfo commandBufferInheritanceInfo = {}; commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; commandBufferInheritanceInfo.pNext = nullptr; commandBufferInheritanceInfo.renderPass = nullptr; commandBufferInheritanceInfo.subpass = 0; commandBufferInheritanceInfo.framebuffer = g_frameBuffers[g_currentBufferIndex]; commandBufferInheritanceInfo.occlusionQueryEnable = VK_FALSE; commandBufferInheritanceInfo.queryFlags = 0; commandBufferInheritanceInfo.pipelineStatistics = 0; VkCommandBufferBeginInfo cmdBeginInfo = {}; cmdBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBeginInfo.pNext = nullptr; cmdBeginInfo.flags = 0; cmdBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo; vkBeginCommandBuffer(command, &cmdBeginInfo); //================================================== // カラーバッファをクリア //================================================== static float count = 0; count += 0.0001f; count = fmodf(count, 1.0f); VkClearColorValue clearColor; clearColor.float32[0] = 0.0f; // R clearColor.float32[1] = count; // G clearColor.float32[2] = 1.0f; // B clearColor.float32[3] = 1.0f; VkImageSubresourceRange imageSubresourceRange; imageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageSubresourceRange.baseMipLevel = 0; imageSubresourceRange.levelCount = 1; imageSubresourceRange.baseArrayLayer = 0; imageSubresourceRange.layerCount = 1; vkCmdClearColorImage( command, g_backBuffersTextures[g_currentBufferIndex].image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &clearColor, 1, &imageSubresourceRange); //================================================== // 深度バッファをクリア //================================================== VkClearDepthStencilValue clearDepthStencil; clearDepthStencil.depth = 1.0f; clearDepthStencil.stencil = 0; imageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; imageSubresourceRange.baseMipLevel = 0; imageSubresourceRange.levelCount = 1; imageSubresourceRange.baseArrayLayer = 0; imageSubresourceRange.layerCount = 1; vkCmdClearDepthStencilImage( command, g_depthBufferTexture.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &clearDepthStencil, 1, &imageSubresourceRange); //================================================== // リソースバリアの設定 //================================================== VkImageMemoryBarrier imageMemoryBarrier; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.pNext = nullptr; imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageMemoryBarrier.subresourceRange.baseMipLevel = 0; imageMemoryBarrier.subresourceRange.levelCount = 1; imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; imageMemoryBarrier.subresourceRange.layerCount = 1; imageMemoryBarrier.image = g_backBuffersTextures[g_currentBufferIndex].image; vkCmdPipelineBarrier( command, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); //================================================== // コマンドの記録を終了 //================================================== vkEndCommandBuffer(command); //================================================== // コマンドを実行し,表示する //================================================== VkPipelineStageFlags pipeStageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.pNext = nullptr; submitInfo.waitSemaphoreCount = 0; submitInfo.pWaitSemaphores = nullptr; submitInfo.pWaitDstStageMask = &pipeStageFlags; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &command; submitInfo.signalSemaphoreCount = 0; submitInfo.pSignalSemaphores = nullptr; // コマンドを実行 result = vkQueueSubmit(g_VulkanQueue, 1, &submitInfo, g_VulkanFence); checkVulkanError(result, TEXT("グラフィックスキューへのサブミット失敗")); // 完了を待機 result = vkWaitForFences(g_VulkanDevice, 1, &g_VulkanFence, VK_TRUE, TIMEOUT_NANO_SEC); // 成功したら表示 if(result == VK_SUCCESS) { VkPresentInfoKHR present = {}; present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present.pNext = nullptr; present.swapchainCount = 1; present.pSwapchains = &g_VulkanSwapChain; present.pImageIndices = &g_currentBufferIndex; present.pWaitSemaphores = nullptr; present.waitSemaphoreCount = 0; present.pResults = nullptr; result = vkQueuePresentKHR(g_VulkanQueue, &present); checkVulkanError(result, TEXT("プレゼント失敗")); } else if(result == VK_TIMEOUT) { checkVulkanError(VK_TIMEOUT, TEXT("タイムアウトしました")); } // フェンスをリセット result = vkResetFences(g_VulkanDevice, 1, &g_VulkanFence); checkVulkanError(result, TEXT("フェンスのリセット失敗")); // 次のイメージを取得 result = vkAcquireNextImageKHR( g_VulkanDevice, g_VulkanSwapChain, TIMEOUT_NANO_SEC, g_VulkanSemahoreRenderComplete, nullptr, &g_currentBufferIndex); checkVulkanError(result, TEXT("次の有効なイメージインデックスの獲得に失敗")); }