diff --git a/01.HelloWorld/main.cpp b/01.HelloWorld/main.cpp index 0ad93b3e0..60054d1e1 100644 --- a/01.HelloWorld/main.cpp +++ b/01.HelloWorld/main.cpp @@ -294,7 +294,6 @@ Choose Graphics API: uint32_t minSwapchainImageCount(~0u); video::ISurface::SFormat surfaceFormat; video::ISurface::E_PRESENT_MODE presentMode; - asset::E_SHARING_MODE imageSharingMode; VkExtent2D swapchainExtent; // Todo(achal): Look at this: @@ -372,12 +371,10 @@ Choose Graphics API: if (graphicsFamilyIndex == presentFamilyIndex) { deviceCreationParams.queueParamsCount = 1u; - imageSharingMode = asset::ESM_EXCLUSIVE; } else { deviceCreationParams.queueParamsCount = 2u; - imageSharingMode = asset::ESM_CONCURRENT; } std::vector queueFamilyIndices(deviceCreationParams.queueParamsCount); @@ -402,6 +399,9 @@ Choose Graphics API: deviceCreationParams.requiredFeatures = requiredFeatures_Device; device = gpu->createLogicalDevice(std::move(deviceCreationParams)); + // no point concurrent sharing mode if only using one queue + if (queueFamilyIndices.size()<2) + queueFamilyIndices.clear(); graphicsQueue = device->getQueue(graphicsFamilyIndex, 0u); presentQueue = device->getQueue(presentFamilyIndex, 0u); @@ -415,7 +415,6 @@ Choose Graphics API: sc_params.height = WIN_H; sc_params.queueFamilyIndexCount = static_cast(queueFamilyIndices.size()); sc_params.queueFamilyIndices = queueFamilyIndices.data(); - sc_params.imageSharingMode = imageSharingMode; sc_params.preTransform = video::ISurface::EST_IDENTITY_BIT; sc_params.compositeAlpha = video::ISurface::ECA_OPAQUE_BIT; sc_params.imageUsage = asset::IImage::EUF_COLOR_ATTACHMENT_BIT; @@ -429,8 +428,8 @@ Choose Graphics API: attachmentDescription.samples = asset::IImage::ESCF_1_BIT; attachmentDescription.loadOp = video::IGPURenderpass::ELO_CLEAR; // when the first subpass begins with this attachment, clear its color and depth components attachmentDescription.storeOp = video::IGPURenderpass::ESO_STORE; // when the last subpass ends with this attachment, store its results - attachmentDescription.initialLayout = asset::EIL_UNDEFINED; - attachmentDescription.finalLayout = asset::EIL_PRESENT_SRC; + attachmentDescription.initialLayout = asset::IImage::EL_UNDEFINED; + attachmentDescription.finalLayout = asset::IImage::EL_PRESENT_SRC; video::IGPURenderpass::SCreationParams::SSubpassDescription subpassDescription = {}; subpassDescription.flags = video::IGPURenderpass::ESDF_NONE; @@ -441,7 +440,7 @@ Choose Graphics API: video::IGPURenderpass::SCreationParams::SSubpassDescription::SAttachmentRef colorAttRef; { colorAttRef.attachment = 0u; - colorAttRef.layout = asset::EIL_COLOR_ATTACHMENT_OPTIMAL; + colorAttRef.layout = asset::IImage::EL_COLOR_ATTACHMENT_OPTIMAL; } subpassDescription.colorAttachmentCount = 1u; subpassDescription.colorAttachments = &colorAttRef; diff --git a/02.ComputeShader/main.cpp b/02.ComputeShader/main.cpp index edb59a491..641ac4c21 100644 --- a/02.ComputeShader/main.cpp +++ b/02.ComputeShader/main.cpp @@ -7,11 +7,11 @@ using namespace nbl; class ComputeShaderSampleApp : public ApplicationBase { - constexpr static uint32_t WIN_W = 768u; - constexpr static uint32_t WIN_H = 512u; + uint32_t windowWidth = 768u; + uint32_t windowHeight = 512u; constexpr static uint32_t FRAMES_IN_FLIGHT = 5u; static constexpr uint64_t MAX_TIMEOUT = 99999999999999ull; - + core::smart_refctd_ptr windowManager; core::smart_refctd_ptr window; @@ -32,8 +32,10 @@ class ComputeShaderSampleApp : public ApplicationBase core::smart_refctd_ptr logger; core::smart_refctd_ptr inputSystem; video::IGPUObjectFromAssetConverter cpu2gpu; + core::smart_refctd_dynamic_array> m_swapchainImages; int32_t m_resourceIx = -1; + int32_t m_frameIx = 0; core::smart_refctd_ptr m_imageAcquire[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr m_renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; @@ -43,11 +45,29 @@ class ComputeShaderSampleApp : public ApplicationBase core::smart_refctd_ptr m_pipeline = nullptr; core::vector> m_descriptorSets; + core::smart_refctd_ptr m_descriptorSetLayout; // These can be removed after descriptor lifetime tracking core::vector> m_swapchainImageViews; core::smart_refctd_ptr m_inImageView; + core::deque m_qRetiredSwapchainResources; + std::mutex m_resizeLock; + std::condition_variable m_resizeWaitForFrame; + + uint32_t m_swapchainIteration = 0; + std::array m_imageSwapchainIterations; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; + + struct CSwapchainResources : public CommonAPI::IRetiredSwapchainResources + { + nbl::core::smart_refctd_ptr oldImageView = nullptr; + nbl::core::smart_refctd_ptr oldImage = nullptr; + nbl::core::smart_refctd_ptr descriptorSet = nullptr; + + ~CSwapchainResources() override {} + }; + public: void setWindow(core::smart_refctd_ptr&& wnd) override { @@ -99,37 +119,126 @@ class ComputeShaderSampleApp : public ApplicationBase APP_CONSTRUCTOR(ComputeShaderSampleApp); + void createSwapchainImage(uint32_t i) + { + auto& img = m_swapchainImages->begin()[i]; + img = swapchain->createImage(i); + assert(img); + { + video::IGPUImageView::SCreationParams viewParams; + viewParams.format = img->getCreationParameters().format; + viewParams.viewType = asset::IImageView::ET_2D; + viewParams.subresourceRange.aspectMask = asset::IImage::EAF_COLOR_BIT; + viewParams.subresourceRange.baseMipLevel = 0u; + viewParams.subresourceRange.levelCount = 1u; + viewParams.subresourceRange.baseArrayLayer = 0u; + viewParams.subresourceRange.layerCount = 1u; + viewParams.image = img; + + m_swapchainImageViews[i] = logicalDevice->createImageView(std::move(viewParams)); + assert(m_swapchainImageViews[i]); + } + + const uint32_t descriptorPoolSizeCount = 1u; + video::IDescriptorPool::SDescriptorPoolSize poolSizes[descriptorPoolSizeCount]; + poolSizes[0].type = asset::EDT_STORAGE_IMAGE; + poolSizes[0].count = 2u; + + video::IDescriptorPool::E_CREATE_FLAGS descriptorPoolFlags = + static_cast(0); + + core::smart_refctd_ptr descriptorPool + = logicalDevice->createDescriptorPool(descriptorPoolFlags, 1, + descriptorPoolSizeCount, poolSizes); + + m_descriptorSets[i] = logicalDevice->createDescriptorSet(descriptorPool.get(), + core::smart_refctd_ptr(m_descriptorSetLayout)); + + const uint32_t writeDescriptorCount = 2u; + + video::IGPUDescriptorSet::SDescriptorInfo descriptorInfos[writeDescriptorCount]; + video::IGPUDescriptorSet::SWriteDescriptorSet writeDescriptorSets[writeDescriptorCount] = {}; + + // image2D -- my input + { + descriptorInfos[0].image.imageLayout = asset::IImage::EL_GENERAL; + descriptorInfos[0].image.sampler = nullptr; + descriptorInfos[0].desc = m_inImageView; + + writeDescriptorSets[0].dstSet = m_descriptorSets[i].get(); + writeDescriptorSets[0].binding = 1u; + writeDescriptorSets[0].arrayElement = 0u; + writeDescriptorSets[0].count = 1u; + writeDescriptorSets[0].descriptorType = asset::EDT_STORAGE_IMAGE; + writeDescriptorSets[0].info = &descriptorInfos[0]; + } + + // image2D -- swapchain image + { + descriptorInfos[1].image.imageLayout = asset::IImage::EL_GENERAL; + descriptorInfos[1].image.sampler = nullptr; + descriptorInfos[1].desc = m_swapchainImageViews[i]; // shouldn't IGPUDescriptorSet hold a reference to the resources in its descriptors? + + writeDescriptorSets[1].dstSet = m_descriptorSets[i].get(); + writeDescriptorSets[1].binding = 0u; + writeDescriptorSets[1].arrayElement = 0u; + writeDescriptorSets[1].count = 1u; + writeDescriptorSets[1].descriptorType = asset::EDT_STORAGE_IMAGE; + writeDescriptorSets[1].info = &descriptorInfos[1]; + } + + logicalDevice->updateDescriptorSets(writeDescriptorCount, writeDescriptorSets, 0u, nullptr); + m_imageSwapchainIterations[i] = m_swapchainIteration; + } + + void onResize(uint32_t w, uint32_t h) override + { + std::unique_lock guard(m_resizeLock); + windowWidth = w; + windowHeight = h; + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, w, h, swapchain); + assert(swapchain); + m_swapchainIteration++; + m_resizeWaitForFrame.wait(guard); + } + void onAppInitialized_impl() override { const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_STORAGE_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_UNORM, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - CommonAPI::InitWithDefaultExt( - initOutput, - video::EAT_VULKAN, - "02.ComputeShader", - FRAMES_IN_FLIGHT, WIN_W, WIN_H, 3u, - swapchainImageUsage, - surfaceFormat); + std::array acceptableSurfaceFormats = { asset::EF_B8G8R8A8_UNORM }; + + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "02.ComputeShader" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = windowWidth; + initParams.windowHeight = windowHeight; + initParams.swapchainImageCount = 3u; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.acceptableSurfaceFormats = acceptableSurfaceFormats.data(); + initParams.acceptableSurfaceFormatCount = acceptableSurfaceFormats.size(); + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + initParams.windowCb->setApplication(this); system = std::move(initOutput.system); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); physicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); utilities = std::move(initOutput.utilities); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + windowManager = std::move(initOutput.windowManager); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, windowWidth, windowHeight, swapchain); + assert(swapchain); commandPools = std::move(initOutput.commandPools); const auto& computeCommandPools = commandPools[CommonAPI::InitOutput::EQT_COMPUTE]; @@ -145,28 +254,9 @@ class ComputeShaderSampleApp : public ApplicationBase core::smart_refctd_ptr(static_cast(window.get()))); #endif - const auto swapchainImages = swapchain->getImages(); const uint32_t swapchainImageCount = swapchain->getImageCount(); - + m_swapchainImages = core::make_refctd_dynamic_array>>(swapchainImageCount); m_swapchainImageViews.resize(swapchainImageCount); - for (uint32_t i = 0u; i < swapchainImageCount; ++i) - { - auto& img = swapchainImages.begin()[i]; - { - video::IGPUImageView::SCreationParams viewParams; - viewParams.format = img->getCreationParameters().format; - viewParams.viewType = asset::IImageView::ET_2D; - viewParams.subresourceRange.aspectMask = asset::IImage::EAF_COLOR_BIT; - viewParams.subresourceRange.baseMipLevel = 0u; - viewParams.subresourceRange.levelCount = 1u; - viewParams.subresourceRange.baseArrayLayer = 0u; - viewParams.subresourceRange.layerCount = 1u; - viewParams.image = core::smart_refctd_ptr(img); - - m_swapchainImageViews[i] = logicalDevice->createImageView(std::move(viewParams)); - assert(m_swapchainImageViews[i]); - } - } video::IGPUObjectFromAssetConverter CPU2GPU; @@ -181,16 +271,16 @@ class ComputeShaderSampleApp : public ApplicationBase } assert(specializedShader); - + for (size_t i = 0; i < FRAMES_IN_FLIGHT; i++) { logicalDevice->createCommandBuffers( computeCommandPools[i].get(), video::IGPUCommandBuffer::EL_PRIMARY, 1, - m_cmdbuf+i); + m_cmdbuf + i); } - + const uint32_t bindingCount = 2u; video::IGPUDescriptorSetLayout::SBinding bindings[bindingCount]; @@ -207,28 +297,9 @@ class ComputeShaderSampleApp : public ApplicationBase bindings[1].stageFlags = asset::IShader::ESS_COMPUTE; bindings[1].samplers = nullptr; } - core::smart_refctd_ptr dsLayout = + m_descriptorSetLayout = logicalDevice->createDescriptorSetLayout(bindings, bindings + bindingCount); - const uint32_t descriptorPoolSizeCount = 1u; - video::IDescriptorPool::SDescriptorPoolSize poolSizes[descriptorPoolSizeCount]; - poolSizes[0].type = asset::EDT_STORAGE_IMAGE; - poolSizes[0].count = swapchainImageCount + 1u; - - video::IDescriptorPool::E_CREATE_FLAGS descriptorPoolFlags = - static_cast(0); - - core::smart_refctd_ptr descriptorPool - = logicalDevice->createDescriptorPool(descriptorPoolFlags, swapchainImageCount, - descriptorPoolSizeCount, poolSizes); - - m_descriptorSets.resize(swapchainImageCount); - for (uint32_t i = 0u; i < swapchainImageCount; ++i) - { - m_descriptorSets[i] = logicalDevice->createDescriptorSet(descriptorPool.get(), - core::smart_refctd_ptr(dsLayout)); - } - // Todo(achal): Uncomment once the KTX loader works #if 0 constexpr auto cachingFlags = static_cast( @@ -248,8 +319,8 @@ class ComputeShaderSampleApp : public ApplicationBase __debugbreak(); #endif - const uint32_t imageWidth = WIN_W; - const uint32_t imageHeight = WIN_H; + const uint32_t imageWidth = windowWidth; + const uint32_t imageHeight = windowHeight; const uint32_t imageChannelCount = 4u; const uint32_t mipLevels = 1u; // WILL NOT WORK FOR MORE THAN 1 MIPS, but doesn't matter since it is temporary until KTX loading works const size_t imageSize = imageWidth * imageHeight * imageChannelCount * sizeof(uint8_t); @@ -267,7 +338,7 @@ class ComputeShaderSampleApp : public ApplicationBase core::smart_refctd_ptr inImage_CPU = nullptr; { - asset::ICPUImage::SCreationParams creationParams = {}; + video::IGPUImage::SCreationParams creationParams = {}; creationParams.flags = static_cast(0u); creationParams.type = asset::IImage::ET_2D; creationParams.format = asset::EF_R8G8B8A8_UNORM; @@ -275,7 +346,7 @@ class ComputeShaderSampleApp : public ApplicationBase creationParams.mipLevels = mipLevels; creationParams.arrayLayers = 1u; creationParams.samples = asset::IImage::ESCF_1_BIT; - creationParams.tiling = asset::IImage::ET_OPTIMAL; + creationParams.tiling = video::IGPUImage::ET_OPTIMAL; if (apiConnection->getAPIType() == video::EAT_VULKAN || apiConnection->getAPIType() == video::EAT_OPENGL_ES) { @@ -285,10 +356,9 @@ class ComputeShaderSampleApp : public ApplicationBase assert(asset::isFloatingPointFormat(creationParams.format) || asset::isNormalizedFormat(creationParams.format)); } creationParams.usage = core::bitflag(asset::IImage::EUF_STORAGE_BIT) | asset::IImage::EUF_TRANSFER_DST_BIT; - creationParams.sharingMode = asset::ESM_EXCLUSIVE; - creationParams.queueFamilyIndexCount = 1u; + creationParams.queueFamilyIndexCount = 0u; creationParams.queueFamilyIndices = nullptr; - creationParams.initialLayout = asset::EIL_UNDEFINED; + creationParams.initialLayout = asset::IImage::EL_UNDEFINED; auto imageRegions = core::make_refctd_dynamic_array>(1ull); imageRegions->begin()->bufferOffset = 0ull; @@ -325,42 +395,10 @@ class ComputeShaderSampleApp : public ApplicationBase } assert(m_inImageView); + m_descriptorSets.resize(swapchainImageCount); for (uint32_t i = 0u; i < swapchainImageCount; ++i) { - const uint32_t writeDescriptorCount = 2u; - - video::IGPUDescriptorSet::SDescriptorInfo descriptorInfos[writeDescriptorCount]; - video::IGPUDescriptorSet::SWriteDescriptorSet writeDescriptorSets[writeDescriptorCount] = {}; - - // image2D -- swapchain image - { - descriptorInfos[0].image.imageLayout = asset::EIL_GENERAL; - descriptorInfos[0].image.sampler = nullptr; - descriptorInfos[0].desc = m_swapchainImageViews[i]; // shouldn't IGPUDescriptorSet hold a reference to the resources in its descriptors? - - writeDescriptorSets[0].dstSet = m_descriptorSets[i].get(); - writeDescriptorSets[0].binding = 0u; - writeDescriptorSets[0].arrayElement = 0u; - writeDescriptorSets[0].count = 1u; - writeDescriptorSets[0].descriptorType = asset::EDT_STORAGE_IMAGE; - writeDescriptorSets[0].info = &descriptorInfos[0]; - } - - // image2D -- my input - { - descriptorInfos[1].image.imageLayout = asset::EIL_GENERAL; - descriptorInfos[1].image.sampler = nullptr; - descriptorInfos[1].desc = m_inImageView; - - writeDescriptorSets[1].dstSet = m_descriptorSets[i].get(); - writeDescriptorSets[1].binding = 1u; - writeDescriptorSets[1].arrayElement = 0u; - writeDescriptorSets[1].count = 1u; - writeDescriptorSets[1].descriptorType = asset::EDT_STORAGE_IMAGE; - writeDescriptorSets[1].info = &descriptorInfos[1]; - } - - logicalDevice->updateDescriptorSets(writeDescriptorCount, writeDescriptorSets, 0u, nullptr); + createSwapchainImage(i); } asset::SPushConstantRange pcRange = {}; @@ -368,7 +406,7 @@ class ComputeShaderSampleApp : public ApplicationBase pcRange.offset = 0u; pcRange.size = 3 * sizeof(uint32_t); core::smart_refctd_ptr pipelineLayout = - logicalDevice->createPipelineLayout(&pcRange, &pcRange + 1, core::smart_refctd_ptr(dsLayout)); + logicalDevice->createPipelineLayout(&pcRange, &pcRange + 1, core::smart_refctd_ptr(m_descriptorSetLayout)); m_pipeline = logicalDevice->createComputePipeline(nullptr, core::smart_refctd_ptr(pipelineLayout), core::smart_refctd_ptr(specializedShader)); @@ -385,6 +423,17 @@ class ComputeShaderSampleApp : public ApplicationBase logicalDevice->waitIdle(); } + std::unique_lock acquireImage(uint32_t* imgnum) + { + while (true) + { + std::unique_lock guard(m_resizeLock); + if (swapchain->acquireNextImage(MAX_TIMEOUT, m_imageAcquire[m_resourceIx].get(), nullptr, imgnum) == nbl::video::ISwapchain::EAIR_SUCCESS) { + return guard; + } + } + } + void workLoopBody() override { m_resourceIx++; @@ -392,23 +441,36 @@ class ComputeShaderSampleApp : public ApplicationBase m_resourceIx = 0; auto& cb = m_cmdbuf[m_resourceIx]; + auto& commandPool = commandPools[CommonAPI::InitOutput::EQT_COMPUTE][m_resourceIx]; auto& fence = m_frameComplete[m_resourceIx]; if (fence) { - while (logicalDevice->waitForFences(1u, &fence.get(), false, MAX_TIMEOUT) == video::IGPUFence::ES_TIMEOUT) - { - } + logicalDevice->blockForFences(1u, &fence.get()); logicalDevice->resetFences(1u, &fence.get()); + if (m_frameIx >= FRAMES_IN_FLIGHT) CommonAPI::dropRetiredSwapchainResources(m_qRetiredSwapchainResources, m_frameIx - FRAMES_IN_FLIGHT); } else fence = logicalDevice->createFence(static_cast(0)); // acquire image uint32_t imgnum = 0u; - swapchain->acquireNextImage(MAX_TIMEOUT, m_imageAcquire[m_resourceIx].get(), nullptr, &imgnum); + std::unique_lock guard = acquireImage(&imgnum); + + if (m_swapchainIteration > m_imageSwapchainIterations[imgnum]) + { + CSwapchainResources* retiredResources(new CSwapchainResources{}); + retiredResources->oldImageView = m_swapchainImageViews[imgnum]; + retiredResources->oldImage = m_swapchainImages->begin()[imgnum]; + retiredResources->descriptorSet = m_descriptorSets[imgnum]; + retiredResources->retiredFrameId = m_frameIx; + + CommonAPI::retireSwapchainResources(m_qRetiredSwapchainResources, retiredResources); + createSwapchainImage(imgnum); + } // safe to proceed - cb->begin(video::IGPUCommandBuffer::EU_ONE_TIME_SUBMIT_BIT); // TODO: Reset Frame's CommandPool + cb->reset(video::IGPUCommandBuffer::ERF_RELEASE_RESOURCES_BIT); // TODO: Begin doesn't release the resources in the command pool, meaning the old swapchains never get dropped + cb->begin(video::IGPUCommandBuffer::EU_ONE_TIME_SUBMIT_BIT); // TODO: Reset Frame's CommandPool { asset::SViewport vp; @@ -416,12 +478,12 @@ class ComputeShaderSampleApp : public ApplicationBase vp.maxDepth = 0.f; vp.x = 0u; vp.y = 0u; - vp.width = WIN_W; - vp.height = WIN_H; + vp.width = windowWidth; + vp.height = windowHeight; cb->setViewport(0u, 1u, &vp); VkRect2D scissor; - scissor.extent = { WIN_W, WIN_H }; + scissor.extent = { windowWidth, windowHeight }; scissor.offset = { 0, 0 }; cb->setScissor(0u, 1u, &scissor); } @@ -435,13 +497,13 @@ class ComputeShaderSampleApp : public ApplicationBase layoutTransBarrier.subresourceRange.baseArrayLayer = 0u; layoutTransBarrier.subresourceRange.layerCount = 1u; - const uint32_t pushConstants[3] = { window->getWidth(), window->getHeight(), swapchain->getPreTransform() }; + const uint32_t pushConstants[3] = { windowWidth, windowHeight, swapchain->getPreTransform() }; layoutTransBarrier.barrier.srcAccessMask = static_cast(0); layoutTransBarrier.barrier.dstAccessMask = asset::EAF_SHADER_WRITE_BIT; - layoutTransBarrier.oldLayout = asset::EIL_UNDEFINED; - layoutTransBarrier.newLayout = asset::EIL_GENERAL; - layoutTransBarrier.image = *(swapchain->getImages().begin() + imgnum); + layoutTransBarrier.oldLayout = asset::IImage::EL_UNDEFINED; + layoutTransBarrier.newLayout = asset::IImage::EL_GENERAL; + layoutTransBarrier.image = *(m_swapchainImages->begin() + imgnum); cb->pipelineBarrier( asset::EPSF_TOP_OF_PIPE_BIT, @@ -455,16 +517,16 @@ class ComputeShaderSampleApp : public ApplicationBase cb->bindDescriptorSets(asset::EPBP_COMPUTE, m_pipeline->getLayout(), 0u, 1u, tmp); cb->bindComputePipeline(m_pipeline.get()); - + const asset::SPushConstantRange& pcRange = m_pipeline->getLayout()->getPushConstantRanges().begin()[0]; cb->pushConstants(m_pipeline->getLayout(), pcRange.stageFlags, pcRange.offset, pcRange.size, pushConstants); - cb->dispatch((WIN_W + 15u) / 16u, (WIN_H + 15u) / 16u, 1u); + cb->dispatch((windowWidth + 15u) / 16u, (windowHeight + 15u) / 16u, 1u); layoutTransBarrier.barrier.srcAccessMask = asset::EAF_SHADER_WRITE_BIT; layoutTransBarrier.barrier.dstAccessMask = static_cast(0); - layoutTransBarrier.oldLayout = asset::EIL_GENERAL; - layoutTransBarrier.newLayout = asset::EIL_PRESENT_SRC; + layoutTransBarrier.oldLayout = asset::IImage::EL_GENERAL; + layoutTransBarrier.newLayout = asset::IImage::EL_PRESENT_SRC; cb->pipelineBarrier( asset::EPSF_COMPUTE_SHADER_BIT, @@ -478,7 +540,6 @@ class ComputeShaderSampleApp : public ApplicationBase CommonAPI::Submit( logicalDevice.get(), - swapchain.get(), cb.get(), queues[CommonAPI::InitOutput::EQT_COMPUTE], m_imageAcquire[m_resourceIx].get(), @@ -491,6 +552,8 @@ class ComputeShaderSampleApp : public ApplicationBase queues[CommonAPI::InitOutput::EQT_COMPUTE], m_renderFinished[m_resourceIx].get(), imgnum); + m_frameIx++; + m_resizeWaitForFrame.notify_all(); } bool keepRunning() override @@ -499,6 +562,9 @@ class ComputeShaderSampleApp : public ApplicationBase } }; -NBL_COMMON_API_MAIN(ComputeShaderSampleApp) +//NBL_COMMON_API_MAIN(ComputeShaderSampleApp) +int main(int argc, char** argv) { + CommonAPI::main(argc, argv); +} extern "C" { _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } \ No newline at end of file diff --git a/03.GPU_Mesh/main.cpp b/03.GPU_Mesh/main.cpp index 078ee4ab7..0c3fd521b 100644 --- a/03.GPU_Mesh/main.cpp +++ b/03.GPU_Mesh/main.cpp @@ -82,7 +82,7 @@ class GPUMesh : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; nbl::video::IGPUObjectFromAssetConverter::SParams cpu2gpuParams; @@ -110,6 +110,8 @@ class GPUMesh : public ApplicationBase core::smart_refctd_ptr renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr commandBuffers[FRAMES_IN_FLIGHT]; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; + void setWindow(core::smart_refctd_ptr&& wnd) override { window = std::move(wnd); @@ -142,7 +144,7 @@ class GPUMesh : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -162,30 +164,43 @@ class GPUMesh : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL_ES, "GPUMesh", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "03.GPUMesh" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); physicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); + for (size_t i = 0ull; i < NBL_FRAMES_TO_AVERAGE; ++i) dtList[i] = 0.0; @@ -285,7 +300,7 @@ class GPUMesh : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; diff --git a/05.NablaTutorialExample/main.cpp b/05.NablaTutorialExample/main.cpp index dd6e4903f..6a5d73571 100644 --- a/05.NablaTutorialExample/main.cpp +++ b/05.NablaTutorialExample/main.cpp @@ -60,7 +60,7 @@ class NablaTutorialExampleApp : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; // TODO: Multibuffer and reset the commandpools nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -83,6 +83,8 @@ class NablaTutorialExampleApp : public ApplicationBase core::smart_refctd_ptr imageAcquire[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr commandBuffers[FRAMES_IN_FLIGHT]; + + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; CommonAPI::InputSystem::ChannelReader mouse; CommonAPI::InputSystem::ChannelReader keyboard; @@ -140,7 +142,7 @@ class NablaTutorialExampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -160,31 +162,43 @@ class NablaTutorialExampleApp : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_VULKAN, "NablaTutorialExample", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "05.NablaTutorialExample" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); physicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); gpuTransferFence = logicalDevice->createFence(static_cast(0)); gpuComputeFence = logicalDevice->createFence(static_cast(0)); @@ -256,7 +270,6 @@ class NablaTutorialExampleApp : public ApplicationBase std::array gpuShaders = { gpuVertexShader.get(), gpuFragmentShader.get() }; size_t ds0SamplerBinding = 0, ds1UboBinding = 0; - auto createAndGetUsefullData = [&](asset::IGeometryCreator::return_type& geometryObject) { /* SBinding for the texture (sampler). @@ -295,14 +308,13 @@ class NablaTutorialExampleApp : public ApplicationBase */ { IGPUBuffer::SCreationParams creationParams = {}; - creationParams.canUpdateSubRange = true; - creationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT)|asset::IBuffer::EUF_TRANSFER_DST_BIT; + creationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT)|asset::IBuffer::EUF_TRANSFER_DST_BIT|asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; creationParams.size = sizeof(SBasicViewParameters); - auto gpuubobuffer = logicalDevice->createBuffer(creationParams); + gpuubo = logicalDevice->createBuffer(std::move(creationParams)); - IDeviceMemoryBacked::SDeviceMemoryRequirements memReq = gpuubobuffer->getMemoryReqs(); + IDeviceMemoryBacked::SDeviceMemoryRequirements memReq = gpuubo->getMemoryReqs(); memReq.memoryTypeBits &= physicalDevice->getDeviceLocalMemoryTypeBits(); - logicalDevice->allocate(memReq, gpuubobuffer.get()); + logicalDevice->allocate(memReq, gpuubo.get()); } /* @@ -314,7 +326,7 @@ class NablaTutorialExampleApp : public ApplicationBase auto descriptorPool = createDescriptorPool(1u); - auto gpuDescriptorSet3 = logicalDevice->createDescriptorSet(descriptorPool.get(), gpuDs3Layout); + gpuDescriptorSet3 = logicalDevice->createDescriptorSet(descriptorPool.get(), gpuDs3Layout); { video::IGPUDescriptorSet::SWriteDescriptorSet write; write.dstSet = gpuDescriptorSet3.get(); @@ -326,13 +338,13 @@ class NablaTutorialExampleApp : public ApplicationBase { info.desc = std::move(gpuImageView); ISampler::SParams samplerParams = { ISampler::ETC_CLAMP_TO_EDGE,ISampler::ETC_CLAMP_TO_EDGE,ISampler::ETC_CLAMP_TO_EDGE,ISampler::ETBC_FLOAT_OPAQUE_BLACK,ISampler::ETF_LINEAR,ISampler::ETF_LINEAR,ISampler::ESMM_LINEAR,0u,false,ECO_ALWAYS }; - info.image = { logicalDevice->createSampler(samplerParams),EIL_SHADER_READ_ONLY_OPTIMAL }; + info.image = { logicalDevice->createSampler(samplerParams),IGPUImage::EL_SHADER_READ_ONLY_OPTIMAL }; } write.info = &info; logicalDevice->updateDescriptorSets(1u, &write, 0u, nullptr); } - auto gpuDescriptorSet1 = logicalDevice->createDescriptorSet(descriptorPool.get(), gpuDs1Layout); + gpuDescriptorSet1 = logicalDevice->createDescriptorSet(descriptorPool.get(), gpuDs1Layout); { video::IGPUDescriptorSet::SWriteDescriptorSet write; write.dstSet = gpuDescriptorSet1.get(); @@ -367,12 +379,12 @@ class NablaTutorialExampleApp : public ApplicationBase Attaching vertex shader and fragment shaders. */ - auto gpuPipeline = logicalDevice->createRenderpassIndependentPipeline(nullptr, std::move(gpuPipelineLayout), gpuShaders.data(), gpuShaders.data() + gpuShaders.size(), geometryObject.inputParams, blendParams, geometryObject.assemblyParams, rasterParams); + gpuRenderpassIndependentPipeline = logicalDevice->createRenderpassIndependentPipeline(nullptr, std::move(gpuPipelineLayout), gpuShaders.data(), gpuShaders.data() + gpuShaders.size(), rectangleGeometry.inputParams, blendParams, rectangleGeometry.assemblyParams, rasterParams); nbl::video::IGPUGraphicsPipeline::SCreationParams graphicsPipelineParams; - graphicsPipelineParams.renderpassIndependent = core::smart_refctd_ptr(gpuPipeline.get()); + graphicsPipelineParams.renderpassIndependent = core::smart_refctd_ptr(gpuRenderpassIndependentPipeline.get()); graphicsPipelineParams.renderpass = core::smart_refctd_ptr(renderpass); - auto gpuGraphicsPipeline = logicalDevice->createGraphicsPipeline(nullptr, std::move(graphicsPipelineParams)); + gpuGraphicsPipeline = logicalDevice->createGraphicsPipeline(nullptr, std::move(graphicsPipelineParams)); core::vectorSIMDf cameraPosition(-5, 0, 0); matrix4SIMD projectionMatrix = matrix4SIMD::buildProjectionMatrixPerspectiveFovLH(core::radians(60.0f), float(WIN_W) / WIN_H, 0.01, 1000); @@ -388,11 +400,11 @@ class NablaTutorialExampleApp : public ApplicationBase cpubuffers.reserve(MAX_DATA_BUFFERS); for (auto i = 0; i < MAX_ATTR_BUF_BINDING_COUNT; i++) { - auto buf = geometryObject.bindings[i].buffer.get(); + auto buf = rectangleGeometry.bindings[i].buffer.get(); if (buf) cpubuffers.push_back(buf); } - auto cpuindexbuffer = geometryObject.indexBuffer.buffer.get(); + auto cpuindexbuffer = rectangleGeometry.indexBuffer.buffer.get(); if (cpuindexbuffer) cpubuffers.push_back(cpuindexbuffer); @@ -403,7 +415,7 @@ class NablaTutorialExampleApp : public ApplicationBase asset::SBufferBinding bindings[MAX_DATA_BUFFERS]; for (auto i = 0, j = 0; i < MAX_ATTR_BUF_BINDING_COUNT; i++) { - if (!geometryObject.bindings[i].buffer) + if (!rectangleGeometry.bindings[i].buffer) continue; auto buffPair = gpubuffers->operator[](j++); bindings[i].offset = buffPair->getOffset(); @@ -416,23 +428,14 @@ class NablaTutorialExampleApp : public ApplicationBase bindings[MAX_ATTR_BUF_BINDING_COUNT].buffer = core::smart_refctd_ptr(buffPair->getBuffer()); } - auto mb = core::make_smart_refctd_ptr(core::smart_refctd_ptr(gpuPipeline), nullptr, bindings, std::move(bindings[MAX_ATTR_BUF_BINDING_COUNT])); + gpuMeshBuffer = core::make_smart_refctd_ptr(core::smart_refctd_ptr(gpuRenderpassIndependentPipeline), nullptr, bindings, std::move(bindings[MAX_ATTR_BUF_BINDING_COUNT])); { - mb->setIndexType(geometryObject.indexType); - mb->setIndexCount(geometryObject.indexCount); - mb->setBoundingBox(geometryObject.bbox); + gpuMeshBuffer->setIndexType(rectangleGeometry.indexType); + gpuMeshBuffer->setIndexCount(rectangleGeometry.indexCount); + gpuMeshBuffer->setBoundingBox(rectangleGeometry.bbox); } + } - return std::make_tuple(mb, gpuPipeline, gpuubo, gpuDescriptorSet1, gpuDescriptorSet3, gpuGraphicsPipeline); - }; - - auto gpuRectangle = createAndGetUsefullData(rectangleGeometry); - gpuMeshBuffer = std::get<0>(gpuRectangle); - gpuRenderpassIndependentPipeline = std::get<1>(gpuRectangle); - gpuubo = std::get<2>(gpuRectangle); - gpuDescriptorSet1 = std::get<3>(gpuRectangle); - gpuDescriptorSet3 = std::get<4>(gpuRectangle); - gpuGraphicsPipeline = std::get<5>(gpuRectangle); const auto& graphicsCommandPools = commandPools[CommonAPI::InitOutput::EQT_GRAPHICS]; for (uint32_t i = 0u; i < FRAMES_IN_FLIGHT; i++) { @@ -551,7 +554,7 @@ class NablaTutorialExampleApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -579,7 +582,7 @@ class NablaTutorialExampleApp : public ApplicationBase commandBuffer->endRenderPass(); commandBuffer->end(); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); } diff --git a/06.MeshLoaders/main.cpp b/06.MeshLoaders/main.cpp index aaad7f349..a818efcc1 100644 --- a/06.MeshLoaders/main.cpp +++ b/06.MeshLoaders/main.cpp @@ -42,7 +42,7 @@ class MeshLoadersApp : public ApplicationBase std::array queues; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -77,6 +77,7 @@ class MeshLoadersApp : public ApplicationBase core::smart_refctd_ptr gpumesh; const asset::ICPUMeshBuffer* firstMeshBuffer; const nbl::asset::COBJMetadata::CRenderpassIndependentPipeline* pipelineMetadata; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; uint32_t ds1UboBinding = 0; int resourceIx; @@ -134,7 +135,7 @@ class MeshLoadersApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -185,31 +186,43 @@ class MeshLoadersApp : public ApplicationBase APP_CONSTRUCTOR(MeshLoadersApp) void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_SRC_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_SRGB, asset::EOTF_sRGB); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_VULKAN, "MeshLoaders", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "03.MeshLoaders" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); physicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); // Occlusion Query { @@ -233,13 +246,11 @@ class MeshLoadersApp : public ApplicationBase const size_t queriesSize = sizeof(uint32_t) * 4; video::IGPUBuffer::SCreationParams gpuuboCreationParams; gpuuboCreationParams.size = queriesSize; - gpuuboCreationParams.canUpdateSubRange = true; - gpuuboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT) | asset::IBuffer::EUF_TRANSFER_DST_BIT; - gpuuboCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + gpuuboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT)|asset::IBuffer::EUF_TRANSFER_DST_BIT|asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; gpuuboCreationParams.queueFamilyIndexCount = 0u; gpuuboCreationParams.queueFamilyIndices = nullptr; - queryResultsBuffer = logicalDevice->createBuffer(gpuuboCreationParams); + queryResultsBuffer = logicalDevice->createBuffer(std::move(gpuuboCreationParams)); auto memReqs = queryResultsBuffer->getMemoryReqs(); memReqs.memoryTypeBits &= physicalDevice->getDeviceLocalMemoryTypeBits(); auto queriesMem = logicalDevice->allocate(memReqs, queryResultsBuffer.get()); @@ -311,13 +322,11 @@ class MeshLoadersApp : public ApplicationBase video::IGPUBuffer::SCreationParams gpuuboCreationParams; gpuuboCreationParams.size = neededDS1UBOsz; - gpuuboCreationParams.canUpdateSubRange = true; - gpuuboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT) | asset::IBuffer::EUF_TRANSFER_DST_BIT; - gpuuboCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + gpuuboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT) | asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; gpuuboCreationParams.queueFamilyIndexCount = 0u; gpuuboCreationParams.queueFamilyIndices = nullptr; - gpuubo = logicalDevice->createBuffer(gpuuboCreationParams); + gpuubo = logicalDevice->createBuffer(std::move(gpuuboCreationParams)); auto gpuuboMemReqs = gpuubo->getMemoryReqs(); gpuuboMemReqs.memoryTypeBits &= physicalDevice->getDeviceLocalMemoryTypeBits(); auto uboMemoryOffset = logicalDevice->allocate(gpuuboMemReqs, gpuubo.get(), video::IDeviceMemoryAllocation::E_MEMORY_ALLOCATE_FLAGS::EMAF_NONE); @@ -392,7 +401,7 @@ class MeshLoadersApp : public ApplicationBase } void onAppTerminated_impl() override { - const auto& fboCreationParams = fbo[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -402,7 +411,7 @@ class MeshLoadersApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -499,7 +508,7 @@ class MeshLoadersApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -544,10 +553,10 @@ class MeshLoadersApp : public ApplicationBase commandBuffer->end(); logicalDevice->resetFences(1, &fence.get()); - CommonAPI::Submit(logicalDevice.get(), - swapchain.get(), + CommonAPI::Submit( + logicalDevice.get(), commandBuffer.get(), - queues[CommonAPI::InitOutput::EQT_GRAPHICS], + queues[CommonAPI::InitOutput::EQT_COMPUTE], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); diff --git a/07.SubpassBaking/main.cpp b/07.SubpassBaking/main.cpp index cc58e5bfc..5d7752dcc 100644 --- a/07.SubpassBaking/main.cpp +++ b/07.SubpassBaking/main.cpp @@ -36,7 +36,7 @@ class SubpassBaking : public ApplicationBase std::array queues; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -66,6 +66,7 @@ class SubpassBaking : public ApplicationBase core::smart_refctd_ptr occlusionQueryPool; core::smart_refctd_ptr timestampQueryPool; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; uint32_t acquiredNextFBO = {}; int resourceIx = -1; @@ -102,7 +103,7 @@ class SubpassBaking : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -141,29 +142,44 @@ class SubpassBaking : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_SRC_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_SRGB, asset::EOTF_sRGB); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_VULKAN, "SubpassBaking", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "03.MeshLoaders" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); - physicalDevice = std::move(initOutput.physicalDevice); + utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); + physicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); + system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); + cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); - system = std::move(initOutput.system); - windowCb = std::move(initOutput.windowCb); - cpu2gpuParams = std::move(initOutput.cpu2gpuParams); - utilities = std::move(initOutput.utilities); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); + auto defaultGraphicsCommandPool = commandPools[CommonAPI::InitOutput::EQT_GRAPHICS][0]; auto defaultTransferUpCommandPool = commandPools[CommonAPI::InitOutput::EQT_TRANSFER_UP][0]; @@ -241,13 +257,11 @@ class SubpassBaking : public ApplicationBase video::IGPUBuffer::SCreationParams cameraUBOCreationParams; - cameraUBOCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT); - cameraUBOCreationParams.canUpdateSubRange = true; - cameraUBOCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + cameraUBOCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); cameraUBOCreationParams.queueFamilyIndexCount = 0u; cameraUBOCreationParams.queueFamilyIndices = nullptr; cameraUBOCreationParams.size = neededDS1UBOsz; - cameraUBO = logicalDevice->createBuffer(cameraUBOCreationParams); + cameraUBO = logicalDevice->createBuffer(std::move(cameraUBOCreationParams)); auto ubomemreq = cameraUBO->getMemoryReqs(); ubomemreq.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -424,10 +438,9 @@ class SubpassBaking : public ApplicationBase asset::SBufferBinding scratch; { video::IGPUBuffer::SCreationParams scratchParams = {}; - scratchParams.canUpdateSubRange = true; - scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT) | video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT; + scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT) | video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT | video::IGPUBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; scratchParams.size = ppHandler->getMaxScratchSize(); - auto scratchBuff = logicalDevice->createBuffer(scratchParams); + auto scratchBuff = logicalDevice->createBuffer(std::move(scratchParams)); auto memReqs = scratchBuff->getMemoryReqs(); memReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, scratchBuff.get()); @@ -480,7 +493,7 @@ class SubpassBaking : public ApplicationBase void onAppTerminated_impl() override { - const auto& fboCreationParams = fbo[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -490,7 +503,7 @@ class SubpassBaking : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -590,7 +603,7 @@ class SubpassBaking : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -610,7 +623,7 @@ class SubpassBaking : public ApplicationBase commandBuffer->end(); } - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); getAndLogQueryPoolResults(); diff --git a/09.ColorSpaceTest/main.cpp b/09.ColorSpaceTest/main.cpp index 187f41779..814728793 100644 --- a/09.ColorSpaceTest/main.cpp +++ b/09.ColorSpaceTest/main.cpp @@ -43,7 +43,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase std::array queues; core::smart_refctd_ptr swapchain; core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; core::smart_refctd_ptr system; core::smart_refctd_ptr assetManager; @@ -51,6 +51,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase core::smart_refctd_ptr logger; core::smart_refctd_ptr inputSystem; video::IGPUObjectFromAssetConverter cpu2gpu; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; public: void setWindow(core::smart_refctd_ptr&& wnd) override @@ -71,35 +72,42 @@ class ColorSpaceTestSampleApp : public ApplicationBase void onAppInitialized_impl() override { const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_SRC_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_SRGB, asset::ECP_SRGB, asset::EOTF_sRGB); - - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - CommonAPI::InitWithDefaultExt( - initOutput, - video::EAT_VULKAN, - "09.ColorSpaceTest", - FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, - swapchainImageUsage, - surfaceFormat); + + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "09.ColorSpaceTest" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = 3u; + initParams.swapchainImageUsage = swapchainImageUsage; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); system = std::move(initOutput.system); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); physicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); utilities = std::move(initOutput.utilities); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_UNKNOWN + ); video::IGPUObjectFromAssetConverter cpu2gpu; @@ -304,7 +312,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase { info.desc = gpuImageView; info.image.sampler = nullptr; - info.image.imageLayout = nbl::asset::EIL_SHADER_READ_ONLY_OPTIMAL; + info.image.imageLayout = nbl::asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; } nbl::video::IGPUDescriptorSet::SWriteDescriptorSet write; @@ -401,7 +409,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase clear.color.float32[2] = 1.f; clear.color.float32[3] = 1.f; beginInfo.clearValueCount = 1u; - beginInfo.framebuffer = fbos[imgnum]; + beginInfo.framebuffer = fbos->begin()[imgnum]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = &clear; @@ -416,7 +424,6 @@ class ColorSpaceTestSampleApp : public ApplicationBase CommonAPI::Submit( logicalDevice.get(), - swapchain.get(), cb.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), @@ -433,7 +440,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase logicalDevice->waitIdle(); - const auto& fboCreationParams = fbos[imgnum]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[imgnum]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; const std::string writePath = "screenShot_" + captionData.name + ".png"; @@ -445,7 +452,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), writePath, - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); }; @@ -497,7 +504,7 @@ class ColorSpaceTestSampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override diff --git a/11.LoDSystem/main.cpp b/11.LoDSystem/main.cpp index b80eef104..3534100f0 100644 --- a/11.LoDSystem/main.cpp +++ b/11.LoDSystem/main.cpp @@ -323,7 +323,7 @@ class LoDSystemApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -341,30 +341,42 @@ class LoDSystemApp : public ApplicationBase APP_CONSTRUCTOR(LoDSystemApp) void onAppInitialized_impl() override { - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_DST_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL, "Level of Detail System", FRAMES_IN_FLIGHT, WIN_W, WIN_H, FBO_COUNT, swapchainImageUsage, surfaceFormat, asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "11.LoDSystem" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = FBO_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + + window = std::move(initParams.window); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); system = std::move(initOutput.system); - windowCallback = std::move(initOutput.windowCb); + windowCallback = std::move(initParams.windowCb); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); utilities = std::move(initOutput.utilities); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); transferUpQueue = queues[CommonAPI::InitOutput::EQT_TRANSFER_UP]; auto defaultGraphicsCommandPool = commandPools[CommonAPI::InitOutput::EQT_GRAPHICS][0]; @@ -429,7 +441,7 @@ class LoDSystemApp : public ApplicationBase params.usage = asset::IBuffer::EUF_STORAGE_BUFFER_BIT; params.size = sizeof(uint32_t) + sizeof(scene::ITransformTree::node_t) * MaxInstanceCount; - nodeList = {0ull,~0ull, logicalDevice->createBuffer(params)}; + nodeList = {0ull,~0ull, logicalDevice->createBuffer(std::move(params))}; nodeList.buffer->setObjectDebugName("transformTreeNodeList"); auto nodeListMemReqs = nodeList.buffer->getMemoryReqs(); nodeListMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -438,7 +450,7 @@ class LoDSystemApp : public ApplicationBase video::IGPUBuffer::SCreationParams cullparams; cullparams.usage = asset::IBuffer::EUF_STORAGE_BUFFER_BIT; cullparams.size = sizeof(culling_system_t::InstanceToCull) * MaxInstanceCount; - cullingParams.instanceList = {0ull,~0ull,logicalDevice->createBuffer(cullparams) }; + cullingParams.instanceList = {0ull,~0ull,logicalDevice->createBuffer(std::move(cullparams)) }; auto cullbufMemReqs = cullingParams.instanceList.buffer->getMemoryReqs(); cullbufMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -671,10 +683,9 @@ class LoDSystemApp : public ApplicationBase asset::SBufferBinding scratch; { video::IGPUBuffer::SCreationParams scratchParams = {}; - scratchParams.canUpdateSubRange = true; - scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT) | video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT; + scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT) | video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT | video::IGPUBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; scratchParams.size = ppHandler->getMaxScratchSize(); - scratch = { 0ull,logicalDevice->createBuffer(scratchParams) }; + scratch = { 0ull,logicalDevice->createBuffer(std::move(scratchParams)) }; scratch.buffer->setObjectDebugName("Scratch Buffer"); auto scratchMemReqs = scratch.buffer->getMemoryReqs(); scratchMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -759,7 +770,7 @@ class LoDSystemApp : public ApplicationBase lodLibrary->clear(); drawIndirectAllocator->clear(); - const auto& fboCreationParams = fbos[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -769,7 +780,7 @@ class LoDSystemApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -877,7 +888,7 @@ class LoDSystemApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbos[acquiredNextFBO]; + beginInfo.framebuffer = fbos->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -890,7 +901,7 @@ class LoDSystemApp : public ApplicationBase commandBuffer->end(); } - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); } @@ -910,7 +921,7 @@ class LoDSystemApp : public ApplicationBase std::array queues; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr assetManager; @@ -941,6 +952,7 @@ class LoDSystemApp : public ApplicationBase core::smart_refctd_ptr frameComplete[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr imageAcquire[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; video::CDumbPresentationOracle oracle; uint32_t acquiredNextFBO = {}; diff --git a/12.glTF/main.cpp b/12.glTF/main.cpp index 198e8af97..2fc7c4db9 100644 --- a/12.glTF/main.cpp +++ b/12.glTF/main.cpp @@ -65,7 +65,7 @@ class GLTFApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -84,28 +84,43 @@ class GLTFApp : public ApplicationBase APP_CONSTRUCTOR(GLTFApp) void onAppInitialized_impl() override { - initOutput.window = core::smart_refctd_ptr(window); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL, "glTF", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "12.glTF" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); system = std::move(initOutput.system); - windowCallback = std::move(initOutput.windowCb); + windowCallback = std::move(initParams.windowCb); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); utilities = std::move(initOutput.utilities); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); transferUpQueue = queues[CommonAPI::InitOutput::EQT_TRANSFER_UP]; auto defaultTransferUpCommandPool = commandPools[CommonAPI::InitOutput::EQT_TRANSFER_UP][0]; @@ -211,10 +226,9 @@ class GLTFApp : public ApplicationBase asset::SBufferBinding xferScratch; { video::IGPUBuffer::SCreationParams scratchParams; - scratchParams.canUpdateSubRange = true; - scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT)|video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT; + scratchParams.usage = core::bitflag(video::IGPUBuffer::EUF_TRANSFER_DST_BIT)|video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT|video::IGPUBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; scratchParams.size = ppHandler->getMaxScratchSize(); - xferScratch = {0ull,logicalDevice->createBuffer(scratchParams)}; + xferScratch = {0ull,logicalDevice->createBuffer(std::move(scratchParams))}; xferScratch.buffer->setObjectDebugName("PropertyPoolHandler Scratch Buffer"); auto xferScratchMemReqs = xferScratch.buffer->getMemoryReqs(); xferScratchMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -465,7 +479,7 @@ class GLTFApp : public ApplicationBase IGPUBuffer::SCreationParams iotaBufferParams = {}; iotaBufferParams.usage = core::bitflag(IGPUBuffer::EUF_STORAGE_BUFFER_BIT)|IGPUBuffer::EUF_VERTEX_BUFFER_BIT; iotaBufferParams.size = pivotNodesRange.size / sizeof(scene::ITransformTree::node_t); - iotaBinding = {0ull,logicalDevice->createBuffer(iotaBufferParams)}; + iotaBinding = {0ull,logicalDevice->createBuffer(std::move(iotaBufferParams))}; auto memReqs = iotaBinding.buffer->getMemoryReqs(); memReqs.memoryTypeBits &= gpuPhysicalDevice->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, iotaBinding.buffer.get()); @@ -800,7 +814,7 @@ class GLTFApp : public ApplicationBase void onAppTerminated_impl() override { - const auto& fboCreationParams = fbos[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -810,7 +824,7 @@ class GLTFApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); } @@ -943,7 +957,7 @@ class GLTFApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbos[acquiredNextFBO]; + beginInfo.framebuffer = fbos->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -1022,7 +1036,7 @@ class GLTFApp : public ApplicationBase commandBuffer->endRenderPass(); commandBuffer->end(); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[decltype(initOutput)::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[decltype(initOutput)::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[decltype(initOutput)::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); } @@ -1041,7 +1055,7 @@ class GLTFApp : public ApplicationBase std::array queues; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr assetManager; nbl::core::smart_refctd_ptr logger; @@ -1082,6 +1096,7 @@ class GLTFApp : public ApplicationBase core::smart_refctd_ptr frameComplete[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr imageAcquire[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; video::CDumbPresentationOracle oracle; diff --git a/14.ComputeScan/main.cpp b/14.ComputeScan/main.cpp index feb42dc06..2be165205 100644 --- a/14.ComputeScan/main.cpp +++ b/14.ComputeScan/main.cpp @@ -20,16 +20,19 @@ class ComputeScanApp : public NonGraphicalApplicationBase NON_GRAPHICAL_APP_CONSTRUCTOR(ComputeScanApp) void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.system = core::smart_refctd_ptr(system); - CommonAPI::InitWithNoExt(initOutput, video::EAT_VULKAN, "Subgroup Arithmetic Test"); + CommonAPI::InitParams initParams; + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "14.Subgroup Arithmetic Test" }; + initParams.swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS(0); + auto initOutput = CommonAPI::Init(std::move(initParams)); + system = std::move(initOutput.system); auto gl = std::move(initOutput.apiConnection); auto logger = std::move(initOutput.logger); auto gpuPhysicalDevice = std::move(initOutput.physicalDevice); auto logicalDevice = std::move(initOutput.logicalDevice); auto queues = std::move(initOutput.queues); - auto renderpass = std::move(initOutput.renderpass); + auto renderpass = std::move(initOutput.renderToSwapchainRenderpass); auto commandPools = std::move(initOutput.commandPools); auto assetManager = std::move(initOutput.assetManager); auto cpu2gpuParams = std::move(initOutput.cpu2gpuParams); @@ -54,9 +57,9 @@ class ComputeScanApp : public NonGraphicalApplicationBase // Take (an almost) 64MB portion from it to scan constexpr auto begin = in_count / 4 + 118; - assert(((begin * sizeof(uint32_t)) & (gpuPhysicalDevice->getLimits().SSBOAlignment - 1u)) == 0u); + assert(((begin * sizeof(uint32_t)) & (gpuPhysicalDevice->getLimits().minSSBOAlignment - 1u)) == 0u); constexpr auto end = in_count * 3 / 4 - 78; - assert(((end * sizeof(uint32_t)) & (gpuPhysicalDevice->getLimits().SSBOAlignment - 1u)) == 0u); + assert(((end * sizeof(uint32_t)) & (gpuPhysicalDevice->getLimits().minSSBOAlignment - 1u)) == 0u); constexpr auto elementCount = end - begin; SBufferRange in_gpu_range; @@ -83,7 +86,7 @@ class ComputeScanApp : public NonGraphicalApplicationBase params.size = scratch_gpu_range.size; params.usage = core::bitflag(IGPUBuffer::EUF_STORAGE_BUFFER_BIT) | IGPUBuffer::EUF_TRANSFER_DST_BIT; - scratch_gpu_range.buffer = logicalDevice->createBuffer(params); + scratch_gpu_range.buffer = logicalDevice->createBuffer(std::move(params)); auto memReqs = scratch_gpu_range.buffer->getMemoryReqs(); memReqs.memoryTypeBits &= gpuPhysicalDevice->getDeviceLocalMemoryTypeBits(); auto scratchMem = logicalDevice->allocate(memReqs, scratch_gpu_range.buffer.get()); @@ -164,7 +167,7 @@ class ComputeScanApp : public NonGraphicalApplicationBase params.size = in_gpu_range.size; params.usage = IGPUBuffer::EUF_TRANSFER_DST_BIT; - auto downloaded_buffer = logicalDevice->createBuffer(params); + auto downloaded_buffer = logicalDevice->createBuffer(std::move(params)); auto memReqs = downloaded_buffer->getMemoryReqs(); memReqs.memoryTypeBits &= gpuPhysicalDevice->getDownStreamingMemoryTypeBits(); auto queriesMem = logicalDevice->allocate(memReqs, downloaded_buffer.get()); @@ -267,9 +270,9 @@ NBL_COMMON_API_MAIN(ComputeScanApp) // // // Take (an almost) 64MB portion from it to scan // constexpr auto begin = in_count/4+110; -// assert(((begin*sizeof(uint32_t))&(gpuPhysicalDevice->getLimits().SSBOAlignment-1u))==0u); +// assert(((begin*sizeof(uint32_t))&(gpuPhysicalDevice->getLimits().minSSBOAlignment-1u))==0u); // constexpr auto end = in_count*3/4-78; -// assert(((end*sizeof(uint32_t))&(gpuPhysicalDevice->getLimits().SSBOAlignment-1u))==0u); +// assert(((end*sizeof(uint32_t))&(gpuPhysicalDevice->getLimits().minSSBOAlignment-1u))==0u); // constexpr auto elementCount = end-begin; // // SBufferRange in_gpu_range; diff --git a/16.OrderIndependentTransparency/main.cpp b/16.OrderIndependentTransparency/main.cpp index 821bb22ba..c5501b10c 100644 --- a/16.OrderIndependentTransparency/main.cpp +++ b/16.OrderIndependentTransparency/main.cpp @@ -45,7 +45,7 @@ class OITSampleApp : public ApplicationBase std::array queues; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; // TODO: Multibuffer and reset the commandpools nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -87,6 +87,8 @@ class OITSampleApp : public ApplicationBase core::smart_refctd_ptr oit_resolve_ppln; core::smart_refctd_ptr oit_pass1_pipeline; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; + uint32_t ds1UboBinding = 0; int resourceIx; @@ -141,7 +143,7 @@ class OITSampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -159,44 +161,43 @@ class OITSampleApp : public ApplicationBase APP_CONSTRUCTOR(OITSampleApp) void onAppInitialized_impl() override { - CommonAPI::SFeatureRequest requiredInstanceFeatures = {}; - requiredInstanceFeatures.count = 1u; - video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - - CommonAPI::SFeatureRequest optionalInstanceFeatures = {}; - - CommonAPI::SFeatureRequest requiredDeviceFeatures = {}; - requiredDeviceFeatures.count = 1u; - video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - - CommonAPI::SFeatureRequest< video::ILogicalDevice::E_FEATURE> optionalDeviceFeatures = {}; - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL, "OITSample", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "16.OITSample" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); physicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); bool oit_init = oit.initialize(logicalDevice.get(), WIN_W, WIN_H, cpu2gpuParams); assert(oit_init); @@ -369,15 +370,12 @@ class OITSampleApp : public ApplicationBase video::IGPUBuffer::SCreationParams gpuuboCreationParams; - gpuuboCreationParams.canUpdateSubRange = true; - gpuuboCreationParams.usage = asset::IBuffer::EUF_UNIFORM_BUFFER_BIT; - gpuuboCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_CONCURRENT; + gpuuboCreationParams.usage = asset::IBuffer::E_USAGE_FLAGS(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); gpuuboCreationParams.queueFamilyIndexCount = 0u; gpuuboCreationParams.queueFamilyIndices = nullptr; - gpuuboCreationParams.canUpdateSubRange = true; gpuuboCreationParams.size = neededDS1UBOsz; - gpuubo = logicalDevice->createBuffer(gpuuboCreationParams); + gpuubo = logicalDevice->createBuffer(std::move(gpuuboCreationParams)); auto gpuuboMemReqs = gpuubo->getMemoryReqs(); gpuuboMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(gpuuboMemReqs, gpuubo.get()); @@ -462,7 +460,7 @@ class OITSampleApp : public ApplicationBase } void onAppTerminated_impl() override { - const auto& fboCreationParams = fbo[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -472,7 +470,7 @@ class OITSampleApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -562,7 +560,7 @@ class OITSampleApp : public ApplicationBase clear[1].depthStencil.stencil = 0; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -656,7 +654,6 @@ class OITSampleApp : public ApplicationBase commandBuffer->end(); CommonAPI::Submit(logicalDevice.get(), - swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), diff --git a/20.Megatexture/main.cpp b/20.Megatexture/main.cpp index daedeaa9c..da8413020 100644 --- a/20.Megatexture/main.cpp +++ b/20.Megatexture/main.cpp @@ -288,7 +288,7 @@ class MegaTextureApp : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -313,6 +313,7 @@ class MegaTextureApp : public ApplicationBase uint32_t ds1UboBinding = 0u; core::smart_refctd_ptr gpuubo; core::smart_refctd_ptr gpumesh; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; const asset::COBJMetadata* metaOBJ = nullptr; @@ -348,7 +349,7 @@ class MegaTextureApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -368,31 +369,43 @@ APP_CONSTRUCTOR(MegaTextureApp) void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL_ES, "MeshLoaders", FRAMES_IN_FLIGHT, WIN_W, WIN_H, FBO_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "20.Megatextures" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = FBO_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); gpuPhysicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); const auto& graphicsCommandPools = commandPools[CommonAPI::InitOutput::EQT_GRAPHICS]; for (uint32_t i = 0u; i < FRAMES_IN_FLIGHT; i++) @@ -617,11 +630,10 @@ APP_CONSTRUCTOR(MegaTextureApp) video::IGPUBuffer::SCreationParams gpuuboCreationParams; gpuuboCreationParams.usage = asset::IBuffer::EUF_UNIFORM_BUFFER_BIT; - gpuuboCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_CONCURRENT; gpuuboCreationParams.queueFamilyIndexCount = 0u; gpuuboCreationParams.queueFamilyIndices = nullptr; gpuuboCreationParams.size = neededDS1UBOsz; - gpuubo = logicalDevice->createBuffer(gpuuboCreationParams); + gpuubo = logicalDevice->createBuffer(std::move(gpuuboCreationParams)); auto gpuuboMemReqs = gpuubo->getMemoryReqs(); gpuuboMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(gpuuboMemReqs, gpuubo.get()); @@ -739,7 +751,7 @@ APP_CONSTRUCTOR(MegaTextureApp) clear.color.float32[2] = 1.f; clear.color.float32[3] = 1.f; beginInfo.clearValueCount = 1u; - beginInfo.framebuffer = fbos[0]; + beginInfo.framebuffer = fbos->begin()[0]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = &clear; @@ -803,7 +815,7 @@ APP_CONSTRUCTOR(MegaTextureApp) constexpr uint64_t MAX_TIMEOUT = 99999999999999ull; // ns swapchain->acquireNextImage(MAX_TIMEOUT, img_acq_sem.get(), nullptr, &imgnum); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], img_acq_sem.get(), render_finished_sem.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], img_acq_sem.get(), render_finished_sem.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], render_finished_sem.get(), imgnum); } diff --git a/21.DynamicTextureIndexing/main.cpp b/21.DynamicTextureIndexing/main.cpp index 1d0da5437..e762736e8 100644 --- a/21.DynamicTextureIndexing/main.cpp +++ b/21.DynamicTextureIndexing/main.cpp @@ -49,7 +49,7 @@ class DynamicTextureIndexingApp : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -101,6 +101,7 @@ class DynamicTextureIndexingApp : public ApplicationBase core::vector packedMeshBuffer; core::vector mdiCallParams; core::vector> gpuIndirectDrawBuffer; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; uint32_t ds1UboBinding = 0; int resourceIx; @@ -154,7 +155,7 @@ class DynamicTextureIndexingApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -175,36 +176,42 @@ class DynamicTextureIndexingApp : public ApplicationBase void onAppInitialized_impl() override { const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_STORAGE_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_UNORM, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - CommonAPI::InitWithDefaultExt( - initOutput, - video::EAT_OPENGL, - "DynamicTextureIndexing", - FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, - swapchainImageUsage, - surfaceFormat, - nbl::asset::EF_D32_SFLOAT); - - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "21.DynamicTextureIndexing" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); utilities = std::move(initOutput.utilities); logicalDevice = std::move(initOutput.logicalDevice); gpuPhysicalDevice = initOutput.physicalDevice; queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); descriptorPool = createDescriptorPool(1u); @@ -473,7 +480,7 @@ class DynamicTextureIndexingApp : public ApplicationBase } } - info[bind].image.imageLayout = asset::EIL_SHADER_READ_ONLY_OPTIMAL; + info[bind].image.imageLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; info[bind].image.sampler = core::smart_refctd_ptr(sampler); info[bind].desc = core::smart_refctd_ptr(gpuTexture); @@ -617,7 +624,7 @@ class DynamicTextureIndexingApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[acquiredNextFBO]; + beginInfo.framebuffer = fbo->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -646,7 +653,6 @@ class DynamicTextureIndexingApp : public ApplicationBase commandBuffer->end(); CommonAPI::Submit(logicalDevice.get(), - swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), @@ -659,7 +665,7 @@ class DynamicTextureIndexingApp : public ApplicationBase void onAppTerminated_impl() override { - const auto& fboCreationParams = fbo[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -669,7 +675,7 @@ class DynamicTextureIndexingApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); diff --git a/27.PLYSTLDemo/main.cpp b/27.PLYSTLDemo/main.cpp index a8c638f64..b398a4e9a 100644 --- a/27.PLYSTLDemo/main.cpp +++ b/27.PLYSTLDemo/main.cpp @@ -52,7 +52,7 @@ class PLYSTLDemo : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -72,6 +72,8 @@ class PLYSTLDemo : public ApplicationBase core::smart_refctd_ptr frameComplete[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr imageAcquire[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; + + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; std::chrono::system_clock::time_point lastTime; bool frameDataFilled = false; @@ -122,7 +124,7 @@ class PLYSTLDemo : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -142,30 +144,43 @@ APP_CONSTRUCTOR(PLYSTLDemo) void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_VULKAN, "plystldemo", FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "27.plystldemo" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); system = std::move(initOutput.system); - windowCallback = std::move(initOutput.windowCb); + windowCallback = std::move(initParams.windowCb); utilities = std::move(initOutput.utilities); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); + auto defaultComputeCommandPool = commandPools[CommonAPI::InitOutput::EQT_COMPUTE][0]; auto defaultTransferUpCommandPool = commandPools[CommonAPI::InitOutput::EQT_TRANSFER_UP][0]; @@ -202,7 +217,6 @@ APP_CONSTRUCTOR(PLYSTLDemo) cpu2gpuParams.pipelineCache = nullptr; cpu2gpuParams.limits = gpuPhysicalDevice->getLimits(); cpu2gpuParams.finalQueueFamIx = queues[decltype(initOutput)::EQT_GRAPHICS]->getFamilyIndex(); - cpu2gpuParams.sharingMode = nbl::asset::ESM_EXCLUSIVE; logicalDevice->createCommandBuffers(defaultTransferUpCommandPool.get(),video::IGPUCommandBuffer::EL_PRIMARY,1u,&cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_TRANSFER].cmdbuf); cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_TRANSFER].queue = queues[decltype(initOutput)::EQT_TRANSFER_UP]; @@ -311,14 +325,12 @@ APP_CONSTRUCTOR(PLYSTLDemo) } video::IGPUBuffer::SCreationParams creationParams; - creationParams.canUpdateSubRange = true; - creationParams.usage = asset::IBuffer::E_USAGE_FLAGS::EUF_UNIFORM_BUFFER_BIT; - creationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + creationParams.usage = asset::IBuffer::E_USAGE_FLAGS(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); creationParams.queueFamilyIndices = 0u; creationParams.queueFamilyIndices = nullptr; creationParams.size = uboDS1ByteSize; - auto gpuubo = logicalDevice->createBuffer(creationParams); + auto gpuubo = logicalDevice->createBuffer(std::move(creationParams)); auto gpuuboMemReqs = gpuubo->getMemoryReqs(); gpuuboMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(gpuuboMemReqs, gpuubo.get()); @@ -397,7 +409,7 @@ APP_CONSTRUCTOR(PLYSTLDemo) void onAppTerminated_impl() override { - const auto& fboCreationParams = fbos[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; //TODO: @@ -408,7 +420,7 @@ APP_CONSTRUCTOR(PLYSTLDemo) gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); } @@ -493,7 +505,7 @@ APP_CONSTRUCTOR(PLYSTLDemo) clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbos[acquiredNextFBO]; + beginInfo.framebuffer = fbos->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -576,7 +588,7 @@ APP_CONSTRUCTOR(PLYSTLDemo) commandBuffer->endRenderPass(); commandBuffer->end(); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); } diff --git a/29.SpecializationConstants/main.cpp b/29.SpecializationConstants/main.cpp index 73da6f626..7b5e0c3fb 100644 --- a/29.SpecializationConstants/main.cpp +++ b/29.SpecializationConstants/main.cpp @@ -36,7 +36,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase std::array queues; core::smart_refctd_ptr swapchain; core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; core::smart_refctd_ptr filesystem; core::smart_refctd_ptr assetManager; @@ -76,6 +76,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase core::matrix4SIMD m_viewProj; core::smart_refctd_ptr m_gpuParticleBuf; core::smart_refctd_ptr m_rpIndependentPipeline; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; public: @@ -111,7 +112,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -131,56 +132,43 @@ class SpecializationConstantsSampleApp : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::SFeatureRequest requiredInstanceFeatures = {}; - requiredInstanceFeatures.count = 1u; - video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - - CommonAPI::SFeatureRequest optionalInstanceFeatures = {}; - - CommonAPI::SFeatureRequest requiredDeviceFeatures = {}; - requiredDeviceFeatures.count = 1u; - video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - - CommonAPI::SFeatureRequest< video::ILogicalDevice::E_FEATURE> optionalDeviceFeatures = {}; - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_STORAGE_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_UNORM, asset::ECP_COUNT, asset::EOTF_UNKNOWN); const asset::E_FORMAT depthFormat = asset::EF_UNKNOWN; - - CommonAPI::InitOutput initOutp; - initOutp.window = window; - initOutp.system = system; - CommonAPI::Init( - initOutp, - video::EAT_OPENGL, - "29.SpecializationConstants", - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, - swapchainImageUsage, - surfaceFormat, - depthFormat); - - window = std::move(initOutp.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "29.SpecializationConstants" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = depthFormat; + auto initOutp = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); system = std::move(initOutp.system); - windowCb = std::move(initOutp.windowCb); + windowCb = std::move(initParams.windowCb); api = std::move(initOutp.apiConnection); surface = std::move(initOutp.surface); device = std::move(initOutp.logicalDevice); gpu = std::move(initOutp.physicalDevice); queues = std::move(initOutp.queues); - swapchain = std::move(initOutp.swapchain); - renderpass = std::move(initOutp.renderpass); - fbo = std::move(initOutp.fbo); + renderpass = std::move(initOutp.renderToSwapchainRenderpass); commandPools = std::move(initOutp.commandPools); assetManager = std::move(initOutp.assetManager); filesystem = std::move(initOutp.system); cpu2gpuParams = std::move(initOutp.cpu2gpuParams); utils = std::move(initOutp.utilities); + m_swapchainCreationParams = std::move(initOutp.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(device), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + device, swapchain, renderpass, + depthFormat + ); video::IDescriptorPool::SDescriptorPoolSize poolSize[2]; poolSize[0].count = 1; @@ -281,7 +269,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase video::IGPUBuffer::SCreationParams bufferCreationParams = {}; bufferCreationParams.usage = static_cast(asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_STORAGE_BUFFER_BIT | asset::IBuffer::EUF_VERTEX_BUFFER_BIT); bufferCreationParams.size = 2ull * BUF_SZ; - m_gpuParticleBuf = device->createBuffer(bufferCreationParams); + m_gpuParticleBuf = device->createBuffer(std::move(bufferCreationParams)); m_gpuParticleBuf->setObjectDebugName("m_gpuParticleBuf"); auto particleBufMemReqs = m_gpuParticleBuf->getMemoryReqs(); particleBufMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -294,10 +282,9 @@ class SpecializationConstantsSampleApp : public ApplicationBase particlePosAndVel.clear(); video::IGPUBuffer::SCreationParams uboComputeCreationParams = {}; - uboComputeCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT); + uboComputeCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); uboComputeCreationParams.size = core::roundUp(sizeof(UBOCompute), 64ull); - uboComputeCreationParams.canUpdateSubRange = true; - auto gpuUboCompute = device->createBuffer(uboComputeCreationParams); + auto gpuUboCompute = device->createBuffer(std::move(uboComputeCreationParams)); auto gpuUboComputeMemReqs = gpuUboCompute->getMemoryReqs(); gpuUboComputeMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); device->allocate(gpuUboComputeMemReqs, gpuUboCompute.get()); @@ -375,7 +362,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase m_gpuds0Graphics = device->createDescriptorSet(dscPool.get(), std::move(gpuDs0layoutGraphics)); video::IGPUGraphicsPipeline::SCreationParams gp_params; - gp_params.rasterizationSamplesHint = asset::IImage::ESCF_1_BIT; + gp_params.rasterizationSamples = asset::IImage::ESCF_1_BIT; gp_params.renderpass = core::smart_refctd_ptr(renderpass); gp_params.renderpassIndependent = core::smart_refctd_ptr(m_rpIndependentPipeline); gp_params.subpassIx = 0u; @@ -383,10 +370,9 @@ class SpecializationConstantsSampleApp : public ApplicationBase m_graphicsPipeline = device->createGraphicsPipeline(nullptr, std::move(gp_params)); video::IGPUBuffer::SCreationParams gfxUboCreationParams = {}; - gfxUboCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT); + gfxUboCreationParams.usage = static_cast(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); gfxUboCreationParams.size = sizeof(m_viewParams); - gfxUboCreationParams.canUpdateSubRange = true; - auto gpuUboGraphics = device->createBuffer(gfxUboCreationParams); + auto gpuUboGraphics = device->createBuffer(std::move(gfxUboCreationParams)); auto gpuUboGraphicsMemReqs = gpuUboGraphics->getMemoryReqs(); gpuUboGraphicsMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); @@ -508,7 +494,7 @@ class SpecializationConstantsSampleApp : public ApplicationBase clear.color.float32[2] = 0.f; clear.color.float32[3] = 1.f; info.renderpass = renderpass; - info.framebuffer = fbo[imgnum]; + info.framebuffer = fbo->begin()[imgnum]; info.clearValueCount = 1u; info.clearValues = &clear; info.renderArea.offset = { 0, 0 }; @@ -528,7 +514,6 @@ class SpecializationConstantsSampleApp : public ApplicationBase CommonAPI::Submit( device.get(), - swapchain.get(), cb.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], m_imageAcquire[m_resourceIx].get(), diff --git a/33.Draw3DLine/main.cpp b/33.Draw3DLine/main.cpp index 3e0debb21..2aea8f906 100644 --- a/33.Draw3DLine/main.cpp +++ b/33.Draw3DLine/main.cpp @@ -31,7 +31,7 @@ class Draw3DLineSampleApp : public ApplicationBase std::array queues; core::smart_refctd_ptr sc; core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; core::smart_refctd_ptr assetManager; core::smart_refctd_ptr filesystem; @@ -48,6 +48,8 @@ class Draw3DLineSampleApp : public ApplicationBase core::smart_refctd_ptr m_imageAcquired[FRAMES_IN_FLIGHT] = { nullptr }; core::smart_refctd_ptr m_renderFinished[FRAMES_IN_FLIGHT] = { nullptr }; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; + public: void setWindow(core::smart_refctd_ptr&& wnd) override @@ -82,7 +84,7 @@ class Draw3DLineSampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -102,57 +104,43 @@ class Draw3DLineSampleApp : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::SFeatureRequest requiredInstanceFeatures = {}; - requiredInstanceFeatures.count = 1u; - video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - - CommonAPI::SFeatureRequest optionalInstanceFeatures = {}; - - CommonAPI::SFeatureRequest requiredDeviceFeatures = {}; - requiredDeviceFeatures.count = 1u; - video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - - CommonAPI::SFeatureRequest< video::ILogicalDevice::E_FEATURE> optionalDeviceFeatures = {}; - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_STORAGE_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_UNORM, asset::ECP_COUNT, asset::EOTF_UNKNOWN); const asset::E_FORMAT depthFormat = asset::EF_UNKNOWN; - CommonAPI::InitOutput initOutp; - - initOutp.window = window; - initOutp.system = system; - - CommonAPI::Init( - initOutp, - video::EAT_VULKAN, - "33.Draw3DLine", - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, - swapchainImageUsage, - surfaceFormat, - depthFormat); - - window = std::move(initOutp.window); - windowCb = std::move(initOutp.windowCb); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "33.Draw3DLine" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = depthFormat; + auto initOutp = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); api = std::move(initOutp.apiConnection); surface = std::move(initOutp.surface); device = std::move(initOutp.logicalDevice); gpu = std::move(initOutp.physicalDevice); queues = std::move(initOutp.queues); - sc = std::move(initOutp.swapchain); - renderpass = std::move(initOutp.renderpass); - fbo = std::move(initOutp.fbo); + renderpass = std::move(initOutp.renderToSwapchainRenderpass); commandPools = std::move(initOutp.commandPools); assetManager = std::move(initOutp.assetManager); filesystem = std::move(initOutp.system); cpu2gpuParams = std::move(initOutp.cpu2gpuParams); utils = std::move(initOutp.utilities); + m_swapchainCreationParams = std::move(initOutp.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(device), m_swapchainCreationParams, WIN_W, WIN_H, sc); + assert(sc); + fbo = CommonAPI::createFBOWithSwapchainImages( + sc->getImageCount(), WIN_W, WIN_H, + device, sc, renderpass, + depthFormat + ); m_draw3DLine = ext::DebugDraw::CDraw3DLine::create(device); @@ -186,7 +174,7 @@ class Draw3DLineSampleApp : public ApplicationBase { auto* rpIndependentPipeline = m_draw3DLine->getRenderpassIndependentPipeline(); video::IGPUGraphicsPipeline::SCreationParams gp_params; - gp_params.rasterizationSamplesHint = asset::IImage::ESCF_1_BIT; + gp_params.rasterizationSamples = asset::IImage::ESCF_1_BIT; gp_params.renderpass = core::smart_refctd_ptr(renderpass); gp_params.renderpassIndependent = core::smart_refctd_ptr(rpIndependentPipeline); gp_params.subpassIx = 0u; @@ -257,7 +245,7 @@ class Draw3DLineSampleApp : public ApplicationBase clear.color.float32[2] = 1.f; clear.color.float32[3] = 1.f; info.renderpass = renderpass; - info.framebuffer = fbo[imgnum]; + info.framebuffer = fbo->begin()[imgnum]; info.clearValueCount = 1u; info.clearValues = &clear; info.renderArea = area; @@ -269,7 +257,6 @@ class Draw3DLineSampleApp : public ApplicationBase CommonAPI::Submit( device.get(), - sc.get(), m_cmdbufs[m_resourceIx].get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], m_imageAcquired[m_resourceIx].get(), diff --git a/35.GeometryCreator/main.cpp b/35.GeometryCreator/main.cpp index 40215085f..49e4d8f2b 100644 --- a/35.GeometryCreator/main.cpp +++ b/35.GeometryCreator/main.cpp @@ -151,7 +151,7 @@ class GeometryCreatorSampleApp : public ApplicationBase std::array queues; core::smart_refctd_ptr swapchain; core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; core::smart_refctd_ptr assetManager; video::IGPUObjectFromAssetConverter::SParams cpu2gpuParams; @@ -170,6 +170,7 @@ class GeometryCreatorSampleApp : public ApplicationBase std::unique_ptr m_camera = nullptr; std::unique_ptr m_cpuGpuObjects = nullptr; video::CDumbPresentationOracle oracle; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; public: @@ -205,7 +206,7 @@ class GeometryCreatorSampleApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -225,42 +226,22 @@ class GeometryCreatorSampleApp : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::SFeatureRequest requiredInstanceFeatures = {}; - requiredInstanceFeatures.count = 1u; - video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - - CommonAPI::SFeatureRequest optionalInstanceFeatures = {}; - - CommonAPI::SFeatureRequest requiredDeviceFeatures = {}; - requiredDeviceFeatures.count = 1u; - video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - - CommonAPI::SFeatureRequest< video::ILogicalDevice::E_FEATURE> optionalDeviceFeatures = {}; - - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_SRC_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_B8G8R8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitOutput initOutput; - initOutput.window = window; - initOutput.system = system; - - CommonAPI::Init( - initOutput, - video::EAT_OPENGL, - "35.GeometryCreator", - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - FRAMES_IN_FLIGHT, WIN_W, WIN_H, SC_IMG_COUNT, - swapchainImageUsage, - surfaceFormat, - nbl::asset::EF_D32_SFLOAT); - - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_SRC_BIT); + + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "35.GeometryCreator" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); api = std::move(initOutput.apiConnection); @@ -268,14 +249,21 @@ class GeometryCreatorSampleApp : public ApplicationBase gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); system = std::move(initOutput.system); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); utilities = std::move(initOutput.utilities); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); auto geometryCreator = assetManager->getGeometryCreator(); auto cubeGeometry = geometryCreator->createCubeMesh(vector3df(2, 2, 2)); @@ -487,7 +475,7 @@ class GeometryCreatorSampleApp : public ApplicationBase { logicalDevice->waitIdle(); - const auto& fboCreationParams = fbos[m_acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[m_acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot( @@ -497,7 +485,7 @@ class GeometryCreatorSampleApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -563,7 +551,7 @@ class GeometryCreatorSampleApp : public ApplicationBase clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbos[m_acquiredNextFBO]; + beginInfo.framebuffer = fbos->begin()[m_acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -594,7 +582,6 @@ class GeometryCreatorSampleApp : public ApplicationBase logicalDevice->resetFences(1, &fence.get()); CommonAPI::Submit( logicalDevice.get(), - swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], m_imageAcquire[m_resourceIx].get(), diff --git a/42.FragmentShaderPathTracer/main.cpp b/42.FragmentShaderPathTracer/main.cpp index af37608a0..bdb067adb 100644 --- a/42.FragmentShaderPathTracer/main.cpp +++ b/42.FragmentShaderPathTracer/main.cpp @@ -95,43 +95,27 @@ int main() constexpr bool LOG_TIMESTAMP = false; static_assert(FRAMES_IN_FLIGHT>FBO_COUNT); - CommonAPI::SFeatureRequest requiredInstanceFeatures = {}; - requiredInstanceFeatures.count = 1u; - video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - - CommonAPI::SFeatureRequest optionalInstanceFeatures = {}; - - CommonAPI::SFeatureRequest requiredDeviceFeatures = {}; - requiredDeviceFeatures.count = 1u; - video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - CommonAPI::SFeatureRequest< video::ILogicalDevice::E_FEATURE> optionalDeviceFeatures = {}; optionalDeviceFeatures.count = 2u; video::ILogicalDevice::E_FEATURE optionalFeatures_Device[] = { video::ILogicalDevice::EF_RAY_TRACING_PIPELINE, video::ILogicalDevice::EF_RAY_QUERY }; optionalDeviceFeatures.features = optionalFeatures_Device; const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT | asset::IImage::EUF_TRANSFER_DST_BIT); - const video::ISurface::SFormat surfaceFormat; - - CommonAPI::InitOutput initOutput; - CommonAPI::Init( - initOutput, - video::EAT_VULKAN, - "Compute Shader PathTracer", - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - FRAMES_IN_FLIGHT, WIN_W, WIN_H, FBO_COUNT, - swapchainImageUsage, - surfaceFormat, - asset::EF_D32_SFLOAT); + CommonAPI::InitParams initParams; + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "Compute Shader PathTracer" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = FBO_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.optionalDeviceFeatures = optionalDeviceFeatures; + initParams.depthFormat = asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); auto system = std::move(initOutput.system); - auto window = std::move(initOutput.window); - auto windowCb = std::move(initOutput.windowCb); + auto window = std::move(initParams.window); + auto windowCb = std::move(initParams.windowCb); auto gl = std::move(initOutput.apiConnection); auto surface = std::move(initOutput.surface); auto gpuPhysicalDevice = std::move(initOutput.physicalDevice); @@ -140,9 +124,7 @@ int main() auto graphicsQueue = queues[CommonAPI::InitOutput::EQT_GRAPHICS]; auto transferUpQueue = queues[CommonAPI::InitOutput::EQT_TRANSFER_UP]; auto computeQueue = queues[CommonAPI::InitOutput::EQT_COMPUTE]; - auto swapchain = std::move(initOutput.swapchain); - auto renderpass = std::move(initOutput.renderpass); - auto fbo = std::move(initOutput.fbo); + auto renderpass = std::move(initOutput.renderToSwapchainRenderpass); auto assetManager = std::move(initOutput.assetManager); auto cpu2gpuParams = std::move(initOutput.cpu2gpuParams); auto logger = std::move(initOutput.logger); @@ -150,6 +132,16 @@ int main() auto utilities = std::move(initOutput.utilities); auto graphicsCommandPools = std::move(initOutput.commandPools[CommonAPI::InitOutput::EQT_GRAPHICS]); auto computeCommandPools = std::move(initOutput.commandPools[CommonAPI::InitOutput::EQT_COMPUTE]); + auto swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + core::smart_refctd_ptr swapchain = nullptr; + CommonAPI::createSwapchain(std::move(device), swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + auto fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + device, swapchain, renderpass, + asset::EF_D32_SFLOAT + ); auto graphicsCmdPoolQueueFamIdx = graphicsQueue->getFamilyIndex(); @@ -289,7 +281,7 @@ int main() const size_t size = sampleSequence->getSize(); params.usage = core::bitflag(asset::IBuffer::EUF_TRANSFER_DST_BIT) | asset::IBuffer::EUF_UNIFORM_TEXEL_BUFFER_BIT; params.size = size; - gpuSequenceBuffer = device->createBuffer(params); + gpuSequenceBuffer = device->createBuffer(std::move(params)); auto gpuSequenceBufferMemReqs = gpuSequenceBuffer->getMemoryReqs(); gpuSequenceBufferMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); device->allocate(gpuSequenceBufferMemReqs, gpuSequenceBuffer.get()); @@ -309,7 +301,7 @@ int main() imgParams.arrayLayers = 1u; imgParams.samples = IImage::ESCF_1_BIT; imgParams.usage = core::bitflag(IImage::EUF_SAMPLED_BIT) | IImage::EUF_TRANSFER_DST_BIT; - imgParams.initialLayout = asset::EIL_SHADER_READ_ONLY_OPTIMAL; + imgParams.initialLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; IGPUImage::SBufferCopy region = {}; region.bufferOffset = 0u; @@ -337,7 +329,7 @@ int main() const size_t size = random.size() * sizeof(uint32_t); params.usage = core::bitflag(asset::IBuffer::EUF_TRANSFER_DST_BIT) | asset::IBuffer::EUF_TRANSFER_SRC_BIT; params.size = size; - buffer = device->createBuffer(params); + buffer = device->createBuffer(std::move(params)); auto bufferMemReqs = buffer->getMemoryReqs(); bufferMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); device->allocate(bufferMemReqs, buffer.get()); @@ -378,7 +370,7 @@ int main() { info.desc = outHDRImageViews[i]; info.image.sampler = nullptr; - info.image.imageLayout = asset::E_IMAGE_LAYOUT::EIL_GENERAL; + info.image.imageLayout = asset::IImage::EL_GENERAL; } writeDescriptorSet.info = &info; device->updateDescriptorSets(1u, &writeDescriptorSet, 0u, nullptr); @@ -392,7 +384,7 @@ int main() IGPUBuffer::SCreationParams gpuuboParams = {}; gpuuboParams.usage = core::bitflag(IGPUBuffer::EUF_UNIFORM_BUFFER_BIT) | IGPUBuffer::EUF_TRANSFER_DST_BIT; gpuuboParams.size = sizeof(SBasicViewParametersAligned); - auto gpuubo = device->createBuffer(gpuuboParams); + auto gpuubo = device->createBuffer(std::move(gpuuboParams)); auto gpuuboMemReqs = gpuubo->getMemoryReqs(); gpuuboMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); device->allocate(gpuuboMemReqs, gpuubo.get()); @@ -441,14 +433,14 @@ int main() { // ISampler::SParams samplerParams = { ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETBC_FLOAT_OPAQUE_BLACK, ISampler::ETF_LINEAR, ISampler::ETF_LINEAR, ISampler::ESMM_LINEAR, 0u, false, ECO_ALWAYS }; samplerDescriptorInfo[0].image.sampler = sampler0; - samplerDescriptorInfo[0].image.imageLayout = EIL_SHADER_READ_ONLY_OPTIMAL; + samplerDescriptorInfo[0].image.imageLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; } samplerDescriptorInfo[1].desc = gpuSequenceBufferView; samplerDescriptorInfo[2].desc = gpuScrambleImageView; { // ISampler::SParams samplerParams = { ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETC_CLAMP_TO_EDGE, ISampler::ETBC_INT_OPAQUE_BLACK, ISampler::ETF_NEAREST, ISampler::ETF_NEAREST, ISampler::ESMM_NEAREST, 0u, false, ECO_ALWAYS }; samplerDescriptorInfo[2].image.sampler = sampler1; - samplerDescriptorInfo[2].image.imageLayout = EIL_SHADER_READ_ONLY_OPTIMAL; + samplerDescriptorInfo[2].image.imageLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; } device->updateDescriptorSets(kDescriptorCount, samplerWriteDescriptorSet, 0u, nullptr); @@ -540,8 +532,8 @@ int main() IGPUCommandBuffer::SImageMemoryBarrier imageBarriers[3u] = {}; imageBarriers[0].barrier.srcAccessMask = static_cast(0u); imageBarriers[0].barrier.dstAccessMask = static_cast(asset::EAF_SHADER_WRITE_BIT); - imageBarriers[0].oldLayout = asset::EIL_UNDEFINED; - imageBarriers[0].newLayout = asset::EIL_GENERAL; + imageBarriers[0].oldLayout = asset::IImage::EL_UNDEFINED; + imageBarriers[0].newLayout = asset::IImage::EL_GENERAL; imageBarriers[0].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].image = outHDRImageViews[imgnum]->getCreationParameters().image; @@ -553,8 +545,8 @@ int main() imageBarriers[1].barrier.srcAccessMask = static_cast(0u); imageBarriers[1].barrier.dstAccessMask = static_cast(asset::EAF_SHADER_READ_BIT); - imageBarriers[1].oldLayout = asset::EIL_UNDEFINED; - imageBarriers[1].newLayout = asset::EIL_SHADER_READ_ONLY_OPTIMAL; + imageBarriers[1].oldLayout = asset::IImage::EL_UNDEFINED; + imageBarriers[1].newLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; imageBarriers[1].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[1].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[1].image = gpuScrambleImageView->getCreationParameters().image; @@ -566,8 +558,8 @@ int main() imageBarriers[2].barrier.srcAccessMask = static_cast(0u); imageBarriers[2].barrier.dstAccessMask = static_cast(asset::EAF_SHADER_READ_BIT); - imageBarriers[2].oldLayout = asset::EIL_UNDEFINED; - imageBarriers[2].newLayout = asset::EIL_SHADER_READ_ONLY_OPTIMAL; + imageBarriers[2].oldLayout = asset::IImage::EL_UNDEFINED; + imageBarriers[2].newLayout = asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; imageBarriers[2].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[2].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[2].image = gpuEnvmapImageView->getCreationParameters().image; @@ -594,7 +586,7 @@ int main() // Copy HDR Image to SwapChain auto srcImgViewCreationParams = outHDRImageViews[imgnum]->getCreationParameters(); - auto dstImgViewCreationParams = fbo[imgnum]->getCreationParameters().attachments[0]->getCreationParameters(); + auto dstImgViewCreationParams = fbo->begin()[imgnum]->getCreationParameters().attachments[0]->getCreationParameters(); // Getting Ready for Blit // TRANSITION outHDRImageViews[imgnum] to EIL_TRANSFER_SRC_OPTIMAL @@ -603,8 +595,8 @@ int main() IGPUCommandBuffer::SImageMemoryBarrier imageBarriers[2u] = {}; imageBarriers[0].barrier.srcAccessMask = static_cast(0u); imageBarriers[0].barrier.dstAccessMask = asset::EAF_TRANSFER_WRITE_BIT; - imageBarriers[0].oldLayout = asset::EIL_UNDEFINED; - imageBarriers[0].newLayout = asset::EIL_TRANSFER_SRC_OPTIMAL; + imageBarriers[0].oldLayout = asset::IImage::EL_UNDEFINED; + imageBarriers[0].newLayout = asset::IImage::EL_TRANSFER_SRC_OPTIMAL; imageBarriers[0].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].image = srcImgViewCreationParams.image; @@ -616,8 +608,8 @@ int main() imageBarriers[1].barrier.srcAccessMask = static_cast(0u); imageBarriers[1].barrier.dstAccessMask = asset::EAF_TRANSFER_WRITE_BIT; - imageBarriers[1].oldLayout = asset::EIL_UNDEFINED; - imageBarriers[1].newLayout = asset::EIL_TRANSFER_DST_OPTIMAL; + imageBarriers[1].oldLayout = asset::IImage::EL_UNDEFINED; + imageBarriers[1].newLayout = asset::IImage::EL_TRANSFER_DST_OPTIMAL; imageBarriers[1].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[1].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[1].image = dstImgViewCreationParams.image; @@ -649,7 +641,7 @@ int main() auto srcImg = srcImgViewCreationParams.image; auto dstImg = dstImgViewCreationParams.image; - cb->blitImage(srcImg.get(), EIL_TRANSFER_SRC_OPTIMAL, dstImg.get(), EIL_TRANSFER_DST_OPTIMAL, 1u, &blit , ISampler::ETF_NEAREST); + cb->blitImage(srcImg.get(), asset::IImage::EL_TRANSFER_SRC_OPTIMAL, dstImg.get(), asset::IImage::EL_TRANSFER_DST_OPTIMAL, 1u, &blit , ISampler::ETF_NEAREST); } // TRANSITION `fbo[imgnum]->getCreationParameters().attachments[0]` to EIL_PRESENT @@ -657,8 +649,8 @@ int main() IGPUCommandBuffer::SImageMemoryBarrier imageBarriers[1u] = {}; imageBarriers[0].barrier.srcAccessMask = asset::EAF_TRANSFER_WRITE_BIT; imageBarriers[0].barrier.dstAccessMask = static_cast(0u); - imageBarriers[0].oldLayout = asset::EIL_TRANSFER_DST_OPTIMAL; - imageBarriers[0].newLayout = asset::EIL_PRESENT_SRC; + imageBarriers[0].oldLayout = asset::IImage::EL_TRANSFER_DST_OPTIMAL; + imageBarriers[0].newLayout = asset::IImage::EL_PRESENT_SRC; imageBarriers[0].srcQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].dstQueueFamilyIndex = graphicsCmdPoolQueueFamIdx; imageBarriers[0].image = dstImgViewCreationParams.image; @@ -672,7 +664,7 @@ int main() cb->end(); device->resetFences(1, &fence.get()); - CommonAPI::Submit(device.get(), swapchain.get(), cb.get(), graphicsQueue, imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(device.get(), cb.get(), graphicsQueue, imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(device.get(), swapchain.get(), graphicsQueue, renderFinished[resourceIx].get(), imgnum); if (LOG_TIMESTAMP) @@ -686,7 +678,7 @@ int main() } } - const auto& fboCreationParams = fbo[0]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[0]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; device->waitIdle(); diff --git a/43.SumAndCDFFilters/main.cpp b/43.SumAndCDFFilters/main.cpp index bb06d15f9..29289bc16 100644 --- a/43.SumAndCDFFilters/main.cpp +++ b/43.SumAndCDFFilters/main.cpp @@ -77,11 +77,10 @@ class SumAndCDFFilterSampleApp : public NonGraphicalApplicationBase void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - - initOutput.system = core::smart_refctd_ptr(system); - - CommonAPI::InitWithNoExt(initOutput, EAT_OPENGL, "SumAndCDFFilter"); + CommonAPI::InitParams initParams; + initParams.apiType = video::EAT_OPENGL; + initParams.appName = { "43.SumAndCDFFilter" }; + auto initOutput = CommonAPI::Init(std::move(initParams)); system = std::move(initOutput.system); assetManager = std::move(initOutput.assetManager); diff --git a/47.DerivMapTest/main.cpp b/47.DerivMapTest/main.cpp index 84ce79bcf..8b11243a5 100644 --- a/47.DerivMapTest/main.cpp +++ b/47.DerivMapTest/main.cpp @@ -258,7 +258,7 @@ class DerivMapTestApp : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbos; + nbl::core::smart_refctd_dynamic_array> fbos; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -282,6 +282,8 @@ class DerivMapTestApp : public ApplicationBase core::smart_refctd_ptr gpuDescriptorPool; core::smart_refctd_ptr gpuDescriptorSetLayout3; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; + core::smart_refctd_ptr getCurrentGPURenderpassIndependentPipeline(nbl::video::IGPUImageView* gpuImageView) { switch (gpuImageView->getCreationParameters().viewType) @@ -317,7 +319,7 @@ class DerivMapTestApp : public ApplicationBase info.desc = gpuImageView; nbl::asset::ISampler::SParams samplerParams = { nbl::asset::ISampler::ETC_CLAMP_TO_EDGE, nbl::asset::ISampler::ETC_CLAMP_TO_EDGE, nbl::asset::ISampler::ETC_CLAMP_TO_EDGE, nbl::asset::ISampler::ETBC_FLOAT_OPAQUE_BLACK, nbl::asset::ISampler::ETF_LINEAR, nbl::asset::ISampler::ETF_LINEAR, nbl::asset::ISampler::ESMM_LINEAR, 0u, false, nbl::asset::ECO_ALWAYS }; info.image.sampler = logicalDevice->createSampler(samplerParams); - info.image.imageLayout = nbl::asset::EIL_SHADER_READ_ONLY_OPTIMAL; + info.image.imageLayout = nbl::asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL; } nbl::video::IGPUDescriptorSet::SWriteDescriptorSet write; @@ -405,7 +407,7 @@ class DerivMapTestApp : public ApplicationBase clear.color.float32[2] = 1.f; clear.color.float32[3] = 1.f; beginInfo.clearValueCount = 1u; - beginInfo.framebuffer = fbos[acquiredNextFBO]; + beginInfo.framebuffer = fbos->begin()[acquiredNextFBO]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = &clear; @@ -418,11 +420,11 @@ class DerivMapTestApp : public ApplicationBase commandBuffer->endRenderPass(); commandBuffer->end(); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], imageAcquire[resourceIx].get(), renderFinished[resourceIx].get(), fence.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], renderFinished[resourceIx].get(), acquiredNextFBO); } - const auto& fboCreationParams = fbos[acquiredNextFBO]->getCreationParameters(); + const auto& fboCreationParams = fbos->begin()[acquiredNextFBO]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; const std::string writePath = "screenShot_" + captionData.name + ".png"; @@ -434,7 +436,7 @@ class DerivMapTestApp : public ApplicationBase gpuSourceImageView.get(), assetManager.get(), writePath, - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); return status; @@ -472,7 +474,7 @@ class DerivMapTestApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbos[i] = core::smart_refctd_ptr(f[i]); + fbos->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -492,26 +494,37 @@ class DerivMapTestApp : public ApplicationBase void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_OPENGL, "DerivMapTest", NBL_WINDOW_WIDTH, NBL_WINDOW_HEIGHT, SC_IMG_COUNT, swapchainImageUsage, surfaceFormat); - window = std::move(initOutput.window); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_OPENGL; + initParams.appName = { "47.DerivMapTest" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = NBL_WINDOW_WIDTH; + initParams.windowHeight = NBL_WINDOW_HEIGHT; + initParams.swapchainImageCount = SC_IMG_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbos = std::move(initOutput.fbo); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); + + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, NBL_WINDOW_WIDTH, NBL_WINDOW_HEIGHT, swapchain); + assert(swapchain); + fbos = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), NBL_WINDOW_WIDTH, NBL_WINDOW_HEIGHT, + logicalDevice, swapchain, renderpass, + asset::EF_UNKNOWN + ); auto createDescriptorPool = [&](const uint32_t textureCount) { diff --git a/53.ComputeShaders/main.cpp b/53.ComputeShaders/main.cpp index a5758a425..4de4c3c2c 100644 --- a/53.ComputeShaders/main.cpp +++ b/53.ComputeShaders/main.cpp @@ -143,7 +143,7 @@ class MeshLoadersApp : public ApplicationBase std::array queues = { nullptr, nullptr, nullptr, nullptr }; nbl::core::smart_refctd_ptr swapchain; nbl::core::smart_refctd_ptr renderpass; - std::array, CommonAPI::InitOutput::MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_dynamic_array> fbo; std::array, CommonAPI::InitOutput::MaxFramesInFlight>, CommonAPI::InitOutput::MaxQueuesCount> commandPools; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; @@ -177,6 +177,7 @@ class MeshLoadersApp : public ApplicationBase nbl::core::smart_refctd_ptr gpuMeshBuffer2; core::smart_refctd_ptr gpuGDescriptorSet1; nbl::core::smart_refctd_ptr render_finished_sem; + nbl::video::ISwapchain::SCreationParams m_swapchainCreationParams; void setWindow(core::smart_refctd_ptr&& wnd) override { @@ -210,7 +211,7 @@ class MeshLoadersApp : public ApplicationBase { for (int i = 0; i < f.size(); i++) { - fbo[i] = core::smart_refctd_ptr(f[i]); + fbo->begin()[i] = core::smart_refctd_ptr(f[i]); } } void setSwapchain(core::smart_refctd_ptr&& s) override @@ -230,32 +231,43 @@ APP_CONSTRUCTOR(MeshLoadersApp) void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - initOutput.window = core::smart_refctd_ptr(window); - initOutput.system = core::smart_refctd_ptr(system); - - const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); - const video::ISurface::SFormat surfaceFormat(asset::EF_R8G8B8A8_SRGB, asset::ECP_COUNT, asset::EOTF_UNKNOWN); - - CommonAPI::InitWithDefaultExt(initOutput, video::EAT_VULKAN, "ComputeShaders", FRAMES_IN_FLIGHT, WIN_W, WIN_H, FBO_COUNT, swapchainImageUsage, surfaceFormat, nbl::asset::EF_D32_SFLOAT); - window = std::move(initOutput.window); + const auto swapchainImageUsage = static_cast(asset::IImage::EUF_COLOR_ATTACHMENT_BIT); + CommonAPI::InitParams initParams; + initParams.window = core::smart_refctd_ptr(window); + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "53.ComputeShaders" }; + initParams.framesInFlight = FRAMES_IN_FLIGHT; + initParams.windowWidth = WIN_W; + initParams.windowHeight = WIN_H; + initParams.swapchainImageCount = FBO_COUNT; + initParams.swapchainImageUsage = swapchainImageUsage; + initParams.depthFormat = nbl::asset::EF_D32_SFLOAT; + auto initOutput = CommonAPI::InitWithDefaultExt(std::move(initParams)); + + window = std::move(initParams.window); gl = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); gpuPhysicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); - renderpass = std::move(initOutput.renderpass); - fbo[0] = std::move(initOutput.fbo[0]); + renderpass = std::move(initOutput.renderToSwapchainRenderpass); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); logger = std::move(initOutput.logger); inputSystem = std::move(initOutput.inputSystem); - windowCallback = std::move(initOutput.windowCb); + windowCallback = std::move(initParams.windowCb); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); + m_swapchainCreationParams = std::move(initOutput.swapchainCreationParams); auto defaultGraphicsCommandPool = commandPools[CommonAPI::InitOutput::EQT_GRAPHICS][0]; - + CommonAPI::createSwapchain(std::move(logicalDevice), m_swapchainCreationParams, WIN_W, WIN_H, swapchain); + assert(swapchain); + fbo = CommonAPI::createFBOWithSwapchainImages( + swapchain->getImageCount(), WIN_W, WIN_H, + logicalDevice, swapchain, renderpass, + nbl::asset::EF_D32_SFLOAT + ); + logicalDevice->createCommandBuffers(defaultGraphicsCommandPool.get(), nbl::video::IGPUCommandBuffer::EL_PRIMARY, 1, commandBuffers); auto commandBuffer = commandBuffers[0]; @@ -389,14 +401,12 @@ APP_CONSTRUCTOR(MeshLoadersApp) video::IGPUBuffer::SCreationParams gpuUBOCreationParams; //gpuUBOCreationParams.size = sizeof(SBasicViewParameters); - gpuUBOCreationParams.usage = asset::IBuffer::E_USAGE_FLAGS::EUF_UNIFORM_BUFFER_BIT; - gpuUBOCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + gpuUBOCreationParams.usage = asset::IBuffer::E_USAGE_FLAGS(asset::IBuffer::EUF_UNIFORM_BUFFER_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF); gpuUBOCreationParams.queueFamilyIndexCount = 0u; gpuUBOCreationParams.queueFamilyIndices = nullptr; gpuUBOCreationParams.size = sizeof(SBasicViewParameters); - gpuUBOCreationParams.canUpdateSubRange = true; - gpuUBO = logicalDevice->createBuffer(gpuUBOCreationParams); + gpuUBO = logicalDevice->createBuffer(std::move(gpuUBOCreationParams)); auto gpuUBOmemreqs = gpuUBO->getMemoryReqs(); gpuUBOmemreqs.memoryTypeBits &= gpuPhysicalDevice->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(gpuUBOmemreqs, gpuUBO.get()); @@ -527,7 +537,7 @@ APP_CONSTRUCTOR(MeshLoadersApp) void onAppTerminated_impl() override { - const auto& fboCreationParams = fbo[0]->getCreationParameters(); + const auto& fboCreationParams = fbo->begin()[0]->getCreationParameters(); auto gpuSourceImageView = fboCreationParams.attachments[0]; bool status = ext::ScreenShot::createScreenShot(logicalDevice.get(), @@ -536,7 +546,7 @@ APP_CONSTRUCTOR(MeshLoadersApp) gpuSourceImageView.get(), assetManager.get(), "ScreenShot.png", - asset::EIL_PRESENT_SRC, + asset::IImage::EL_PRESENT_SRC, static_cast(0u)); assert(status); @@ -604,7 +614,7 @@ APP_CONSTRUCTOR(MeshLoadersApp) clear[1].depthStencil.depth = 0.f; beginInfo.clearValueCount = 2u; - beginInfo.framebuffer = fbo[0]; + beginInfo.framebuffer = fbo->begin()[0]; beginInfo.renderpass = renderpass; beginInfo.renderArea = area; beginInfo.clearValues = clear; @@ -671,7 +681,7 @@ APP_CONSTRUCTOR(MeshLoadersApp) constexpr uint64_t MAX_TIMEOUT = 99999999999999ull; // ns swapchain->acquireNextImage(MAX_TIMEOUT, img_acq_sem.get(), nullptr, &imgnum); - CommonAPI::Submit(logicalDevice.get(), swapchain.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], img_acq_sem.get(), render_finished_sem.get()); + CommonAPI::Submit(logicalDevice.get(), commandBuffer.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], img_acq_sem.get(), render_finished_sem.get()); CommonAPI::Present(logicalDevice.get(), swapchain.get(), queues[CommonAPI::InitOutput::EQT_GRAPHICS], render_finished_sem.get(), imgnum); } diff --git a/54.Transformations/main.cpp b/54.Transformations/main.cpp index 72ab71b79..ad2a6433f 100644 --- a/54.Transformations/main.cpp +++ b/54.Transformations/main.cpp @@ -238,13 +238,13 @@ class TransformationApp : public ApplicationBase constexpr uint32_t GlobalTformPropNum = 3u; - const size_t SSBOAlignment = gpuPhysicalDevice->getLimits().SSBOAlignment; + const size_t minSSBOAlignment = gpuPhysicalDevice->getLimits().minSSBOAlignment; const size_t offset_parent = 0u; - const size_t offset_relTform = core::alignUp(offset_parent + parentPropSz * ObjectCount, SSBOAlignment); - const size_t offset_modifStamp = core::alignUp(offset_relTform + relTformPropSz * ObjectCount, SSBOAlignment); - const size_t offset_globalTform = core::alignUp(offset_modifStamp + modifStampPropSz * ObjectCount, SSBOAlignment); - const size_t offset_recompStamp = core::alignUp(offset_globalTform + globalTformPropSz * ObjectCount, SSBOAlignment); - const size_t offset_normalMatrix = core::alignUp(offset_recompStamp + recompStampPropSz * ObjectCount, SSBOAlignment); + const size_t offset_relTform = core::alignUp(offset_parent + parentPropSz * ObjectCount, minSSBOAlignment); + const size_t offset_modifStamp = core::alignUp(offset_relTform + relTformPropSz * ObjectCount, minSSBOAlignment); + const size_t offset_globalTform = core::alignUp(offset_modifStamp + modifStampPropSz * ObjectCount, minSSBOAlignment); + const size_t offset_recompStamp = core::alignUp(offset_globalTform + globalTformPropSz * ObjectCount, minSSBOAlignment); + const size_t offset_normalMatrix = core::alignUp(offset_recompStamp + recompStampPropSz * ObjectCount, minSSBOAlignment); const size_t ssboSz = offset_normalMatrix + normalMatrixPropSz * ObjectCount; diff --git a/55.RGB18E7S3/main.cpp b/55.RGB18E7S3/main.cpp index f5c37db27..d92572d0c 100644 --- a/55.RGB18E7S3/main.cpp +++ b/55.RGB18E7S3/main.cpp @@ -43,15 +43,19 @@ int main() { constexpr std::string_view APP_NAME = "RGB18E7S3 utility test"; - CommonAPI::InitOutput initOutput; - CommonAPI::InitWithNoExt(initOutput, video::EAT_VULKAN, APP_NAME.data()); + CommonAPI::InitParams initParams; + initParams.apiType = video::EAT_VULKAN; + initParams.appName = APP_NAME.data(); + initParams.swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS(0); + auto initOutput = CommonAPI::Init(std::move(initParams)); + auto system = std::move(initOutput.system); auto gl = std::move(initOutput.apiConnection); auto logger = std::move(initOutput.logger); auto gpuPhysicalDevice = std::move(initOutput.physicalDevice); auto logicalDevice = std::move(initOutput.logicalDevice); auto queues = std::move(initOutput.queues); - auto renderpass = std::move(initOutput.renderpass); + auto renderpass = std::move(initOutput.renderToSwapchainRenderpass); auto commandPools = std::move(initOutput.commandPools); auto assetManager = std::move(initOutput.assetManager); auto cpu2gpuParams = std::move(initOutput.cpu2gpuParams); @@ -125,14 +129,12 @@ int main() } video::IGPUBuffer::SCreationParams ssboCreationParams; - ssboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT)|asset::IBuffer::EUF_TRANSFER_DST_BIT; - ssboCreationParams.canUpdateSubRange = true; - ssboCreationParams.sharingMode = asset::E_SHARING_MODE::ESM_EXCLUSIVE; + ssboCreationParams.usage = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT) | asset::IBuffer::EUF_TRANSFER_DST_BIT | asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF; ssboCreationParams.queueFamilyIndexCount = 0u; ssboCreationParams.queueFamilyIndices = nullptr; ssboCreationParams.size = sizeof(SShaderStorageBufferObject); - auto gpuDownloadSSBOmapped = logicalDevice->createBuffer(ssboCreationParams); + auto gpuDownloadSSBOmapped = logicalDevice->createBuffer(std::move(ssboCreationParams)); auto downloadSSBOmemreqs = gpuDownloadSSBOmapped->getMemoryReqs(); downloadSSBOmemreqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getHostVisibleMemoryTypeBits(); logicalDevice->allocate(downloadSSBOmemreqs, gpuDownloadSSBOmapped.get()); diff --git a/56.RayQuery/main.cpp b/56.RayQuery/main.cpp index b642dfb75..5de634903 100644 --- a/56.RayQuery/main.cpp +++ b/56.RayQuery/main.cpp @@ -1154,4 +1154,4 @@ class RayQuerySampleApp : public ApplicationBase } }; -NBL_COMMON_API_MAIN(RayQuerySampleApp) \ No newline at end of file +NBL_COMMON_API_MAIN(RayQuerySampleApp) diff --git a/61.BlitFilterTest/main.cpp b/61.BlitFilterTest/main.cpp index c8990c348..631d324a5 100644 --- a/61.BlitFilterTest/main.cpp +++ b/61.BlitFilterTest/main.cpp @@ -131,19 +131,21 @@ class BlitFilterTestApp : public ApplicationBase public: void onAppInitialized_impl() override { - CommonAPI::InitOutput initOutput; - CommonAPI::InitWithNoExt(initOutput, video::EAT_VULKAN, "BlitFilterTest"); + CommonAPI::InitParams initParams; + initParams.apiType = video::EAT_VULKAN; + initParams.appName = { "BlitFilterTest" }; + initParams.swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS(0); + auto initOutput = CommonAPI::Init(std::move(initParams)); system = std::move(initOutput.system); - window = std::move(initOutput.window); - windowCb = std::move(initOutput.windowCb); + window = std::move(initParams.window); + windowCb = std::move(initParams.windowCb); apiConnection = std::move(initOutput.apiConnection); surface = std::move(initOutput.surface); physicalDevice = std::move(initOutput.physicalDevice); logicalDevice = std::move(initOutput.logicalDevice); utilities = std::move(initOutput.utilities); queues = std::move(initOutput.queues); - swapchain = std::move(initOutput.swapchain); commandPools = std::move(initOutput.commandPools); assetManager = std::move(initOutput.assetManager); cpu2gpuParams = std::move(initOutput.cpu2gpuParams); @@ -378,7 +380,7 @@ class BlitFilterTestApp : public ApplicationBase assert(inImageCPU->getCreationParameters().mipLevels == 1); - auto transitionImageLayout = [this](core::smart_refctd_ptr&& image, const asset::E_IMAGE_LAYOUT finalLayout) + auto transitionImageLayout = [this](core::smart_refctd_ptr&& image, const asset::IImage::E_LAYOUT finalLayout) { core::smart_refctd_ptr cmdbuf = nullptr; logicalDevice->createCommandBuffers(commandPools[CommonAPI::InitOutput::EQT_COMPUTE][0].get(), video::IGPUCommandBuffer::EL_PRIMARY, 1u, &cmdbuf); @@ -386,7 +388,7 @@ class BlitFilterTestApp : public ApplicationBase auto fence = logicalDevice->createFence(video::IGPUFence::ECF_UNSIGNALED); video::IGPUCommandBuffer::SImageMemoryBarrier barrier = {}; - barrier.oldLayout = asset::EIL_UNDEFINED; + barrier.oldLayout = asset::IImage::EL_UNDEFINED; barrier.newLayout = finalLayout; barrier.srcQueueFamilyIndex = ~0u; barrier.dstQueueFamilyIndex = ~0u; @@ -419,7 +421,7 @@ class BlitFilterTestApp : public ApplicationBase // Do layout transition to SHADER_READ_ONLY_OPTIMAL // I think it might be a good idea to allow the user to change asset::ICPUImage's initialLayout and have the asset converter // do the layout transition for them. - transitionImageLayout(core::smart_refctd_ptr(inImage), asset::EIL_SHADER_READ_ONLY_OPTIMAL); + transitionImageLayout(core::smart_refctd_ptr(inImage), asset::IImage::EL_SHADER_READ_ONLY_OPTIMAL); } core::smart_refctd_ptr outImage = nullptr; @@ -440,7 +442,7 @@ class BlitFilterTestApp : public ApplicationBase memReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, outImage.get()); - transitionImageLayout(core::smart_refctd_ptr(outImage), asset::EIL_GENERAL); + transitionImageLayout(core::smart_refctd_ptr(outImage), asset::IImage::EL_GENERAL); } // Create resources needed to do the blit @@ -479,14 +481,15 @@ class BlitFilterTestApp : public ApplicationBase if (normalizationInFormat != outImageFormat) { - video::IGPUImage::SCreationParams creationParams = outImage->getCreationParameters(); + video::IGPUImage::SCreationParams creationParams; + creationParams = outImage->getCreationParameters(); creationParams.format = normalizationInFormat; creationParams.usage = static_cast(video::IGPUImage::EUF_STORAGE_BIT | video::IGPUImage::EUF_SAMPLED_BIT); normalizationInImage = logicalDevice->createImage(std::move(creationParams)); auto memReqs = normalizationInImage->getMemoryReqs(); memReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, normalizationInImage.get()); - transitionImageLayout(core::smart_refctd_ptr(normalizationInImage), asset::EIL_GENERAL); // First we do the blit which requires storage image so starting layout is GENERAL + transitionImageLayout(core::smart_refctd_ptr(normalizationInImage), asset::IImage::EL_GENERAL); // First we do the blit which requires storage image so starting layout is GENERAL video::IGPUImageView::SCreationParams viewCreationParams = {}; viewCreationParams.image = normalizationInImage; @@ -515,7 +518,7 @@ class BlitFilterTestApp : public ApplicationBase creationParams.size = scratchSize; creationParams.usage = static_cast(video::IGPUBuffer::EUF_TRANSFER_DST_BIT | video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT); - coverageAdjustmentScratchBuffer = logicalDevice->createBuffer(creationParams); + coverageAdjustmentScratchBuffer = logicalDevice->createBuffer(std::move(creationParams)); auto memReqs = coverageAdjustmentScratchBuffer->getMemoryReqs(); memReqs.memoryTypeBits &= physicalDevice->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, coverageAdjustmentScratchBuffer.get()); @@ -543,7 +546,7 @@ class BlitFilterTestApp : public ApplicationBase video::IGPUBuffer::SCreationParams creationParams = {}; creationParams.usage = static_cast(video::IGPUBuffer::EUF_STORAGE_BUFFER_BIT | video::IGPUBuffer::EUF_UNIFORM_TEXEL_BUFFER_BIT | video::IGPUBuffer::EUF_TRANSFER_DST_BIT); creationParams.size = lutSize; - auto scaledKernelPhasedLUT = logicalDevice->createBuffer(creationParams); + auto scaledKernelPhasedLUT = logicalDevice->createBuffer(std::move(creationParams)); auto memReqs = scaledKernelPhasedLUT->getMemoryReqs(); memReqs.memoryTypeBits &= physicalDevice->getDeviceLocalMemoryTypeBits(); logicalDevice->allocate(memReqs, scaledKernelPhasedLUT.get()); @@ -626,7 +629,7 @@ class BlitFilterTestApp : public ApplicationBase nullptr, outImageView.get(), static_cast(0u), - asset::EIL_GENERAL); + asset::IImage::EL_GENERAL); if (alphaSemantic == IBlitUtilities::EAS_REFERENCE_OR_COVERAGE) logger->log("GPU alpha coverage: %f", system::ILogger::ELL_DEBUG, computeAlphaCoverage(referenceAlpha, outCPUImageView->getCreationParameters().image.get())); @@ -640,7 +643,7 @@ class BlitFilterTestApp : public ApplicationBase video::IGPUBuffer::SCreationParams creationParams = {}; creationParams.usage = video::IGPUBuffer::EUF_TRANSFER_DST_BIT; creationParams.size = downloadSize; - core::smart_refctd_ptr downloadBuffer = logicalDevice->createBuffer(creationParams); + core::smart_refctd_ptr downloadBuffer = logicalDevice->createBuffer(std::move(creationParams)); auto memReqs = downloadBuffer->getMemoryReqs(); memReqs.memoryTypeBits &= physicalDevice->getDownStreamingMemoryTypeBits(); @@ -658,7 +661,7 @@ class BlitFilterTestApp : public ApplicationBase downloadRegion.imageExtent = outImage->getCreationParameters().extent; // Todo(achal): Transition layout to TRANSFER_SRC_OPTIMAL - cmdbuf->copyImageToBuffer(outImage.get(), asset::EIL_GENERAL, downloadBuffer.get(), 1u, &downloadRegion); + cmdbuf->copyImageToBuffer(outImage.get(), asset::IImage::EL_GENERAL, downloadBuffer.get(), 1u, &downloadRegion); cmdbuf->end(); diff --git a/common/CommonAPI.cpp b/common/CommonAPI.cpp new file mode 100644 index 000000000..a9476e667 --- /dev/null +++ b/common/CommonAPI.cpp @@ -0,0 +1,1030 @@ + +#include "CommonAPI.h" + +std::vector CommonAPI::extractGPUInfos( + nbl::core::SRange gpus, + nbl::core::smart_refctd_ptr surface, + const bool headlessCompute) +{ + using namespace nbl; + using namespace nbl::video; + + std::vector extractedInfos = std::vector(gpus.size()); + + for (size_t i = 0ull; i < gpus.size(); ++i) + { + auto& extractedInfo = extractedInfos[i]; + extractedInfo = {}; + auto gpu = gpus.begin()[i]; + + // Find queue family indices + { + const auto& queueFamilyProperties = gpu->getQueueFamilyProperties(); + + std::vector remainingQueueCounts = std::vector(queueFamilyProperties.size(), 0u); + + for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) + { + const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; + remainingQueueCounts[familyIndex] = familyProperty.queueCount; + } + + // Select Graphics Queue Family Index + if (!headlessCompute) + { + // Select Graphics Queue Family Index + for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) + { + const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; + auto& outFamilyProp = extractedInfo.queueFamilyProps; + + const uint32_t currentFamilyQueueCount = familyProperty.queueCount; + if (currentFamilyQueueCount <= 0) + continue; + + bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); + bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; + bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; + bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; + bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; + bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; + + const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; + const bool hasEnoughQueues = remainingQueueCount >= 1u; + + /* + * Examples: + * -> score is 0 for every queueFam with no Graphics support + * -> If both queue families !hasEnoughtQueues -> score will be equal but this doesn't/shouldn't happen -> there should be a queueFamily with "enoughQueues" for graphics. + * -> if both queue families hasEnoughQueues and have similar support for present and compute: Queue Family with more remainingQueueCount is preferred. + * -> if both queue families hasEnoughQueues with the same number of remainingQueueCount -> "QueueFamily with present and no compute" >>>> "QueueFamily with compute and no present" + * -> if both queue families hasEnoughQueues -> "QueueFamily with compute and no present and 16 remainingQueues" ==== "QueueFamily with present and no compute and 1 remaining Queue" + * -> if both queue families hasEnoughQueues -> "QueueFamily with present and compute and 1 remaining Queue" ==== "QueueFamily with no compute and no present and 34 remaining Queues xD" + */ + uint32_t score = 0u; + if (hasGraphicsFlag) { + score++; + if (hasEnoughQueues) { + score += 1u * remainingQueueCount; + + if (supportsPresent) + { + score += 32u; // more important to have present than compute (presentSupport is larger in scoring to 16 extra compute queues) + } + + if (hasComputeFlag) + { + score += 1u * remainingQueueCount; + } + } + } + + if (score > outFamilyProp.graphics.score) + { + outFamilyProp.graphics.index = familyIndex; + outFamilyProp.graphics.supportsGraphics = hasGraphicsFlag; + outFamilyProp.graphics.supportsCompute = hasComputeFlag; + outFamilyProp.graphics.supportsTransfer = true; // Reporting this is optional for Vk Graphics-Capable QueueFam, but Its support is guaranteed. + outFamilyProp.graphics.supportsSparseBinding = hasSparseBindingFlag; + outFamilyProp.graphics.supportsPresent = supportsPresent; + outFamilyProp.graphics.supportsProtected = hasProtectedFlag; + outFamilyProp.graphics.dedicatedQueueCount = 1u; + outFamilyProp.graphics.score = score; + } + } + assert(extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex); + remainingQueueCounts[extractedInfo.queueFamilyProps.graphics.index] -= extractedInfo.queueFamilyProps.graphics.dedicatedQueueCount; + } + + // Select Compute Queue Family Index + for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) + { + const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; + auto& outFamilyProp = extractedInfo.queueFamilyProps; + + const uint32_t currentFamilyQueueCount = familyProperty.queueCount; + if (currentFamilyQueueCount <= 0) + continue; + + bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); + bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; + bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; + bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; + bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; + bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; + + const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; + const bool hasExtraQueues = remainingQueueCount >= 1u; + + /* + * Examples: + * -> If both !hasEnoughExtraQueues: "queue family that supports graphics" >>>> "queue family that doesn't support graphics" + * -> If both queueFams supports Graphics and hasEnoughExtraQueues: "Graphics-capable QueueFamily equal to the selected Graphics QueueFam" >>>> "Any other Graphics-capable QueueFamily" + * -> If both support Graphics (not equal to graphicsQueueFamIndex): "queue family that hasEnoughExtraQueues" >>>> "queue family that !hasEnoughExtraQueues" + * -> If both support Graphics and hasEnoughExtraQueues (not equal to graphicsQueueFamIndex): both are adequate enough, depends on the order of the queueFams. + * -> "Compute-capable QueueFam with hasEnoughExtraQueues" >>>> "Compute-capable QueueFam with graphics capability and ==graphicsQueueFamIdx with no extra dedicated queues" + */ + uint32_t score = 0u; + if (hasComputeFlag) { + score++; + + if (hasExtraQueues) { + score += 3; + } + + if (!headlessCompute && hasGraphicsFlag) { + score++; + if (familyIndex == outFamilyProp.graphics.index) { + score++; + } + } + } + + if (score > outFamilyProp.compute.score) + { + outFamilyProp.compute.index = familyIndex; + outFamilyProp.compute.supportsGraphics = hasGraphicsFlag; + outFamilyProp.compute.supportsCompute = hasComputeFlag; + outFamilyProp.compute.supportsTransfer = true; // Reporting this is optional for Vk Compute-Capable QueueFam, but Its support is guaranteed. + outFamilyProp.compute.supportsSparseBinding = hasSparseBindingFlag; + outFamilyProp.compute.supportsPresent = supportsPresent; + outFamilyProp.compute.supportsProtected = hasProtectedFlag; + outFamilyProp.compute.dedicatedQueueCount = (hasExtraQueues) ? 1u : 0u; + outFamilyProp.compute.score = score; + } + } + assert(extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex); + remainingQueueCounts[extractedInfo.queueFamilyProps.compute.index] -= extractedInfo.queueFamilyProps.compute.dedicatedQueueCount; + + // Select Transfer Queue Family Index + for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) + { + const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; + auto& outFamilyProp = extractedInfo.queueFamilyProps; + + const uint32_t currentFamilyQueueCount = familyProperty.queueCount; + if (currentFamilyQueueCount <= 0) + continue; + + bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); + bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; + bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; + bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; + bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; + bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; + + const uint32_t extraQueueCount = nbl::core::min(remainingQueueCounts[familyIndex], 2u); // UP + DOWN + const bool hasExtraQueues = extraQueueCount >= 1u; + + /* + * Examples: + * -> score is 0 for every queueFam with no Transfer support + * -> If both have similar hasEnoughExtraQueues, compute and graphics support: the one with more remainingQueueCount is preferred + * -> If both support Transfer: "QueueFam with >=1 extra queues and graphics and compute support" >>>> (less probable)"QueueFam with no extra queues and transfer-only(no compute and graphics support)" + * -> If both support Transfer: "QueueFam with >=0 extra queues and only compute" >>>> "QueueFam with >=0 extra queues and only graphics" + */ + uint32_t score = 0u; + if (hasTransferFlag) { + score += 1u; + + uint32_t notHavingComputeScore = 1u; + uint32_t notHavingGraphicsScore = 2u; + + if (hasExtraQueues) { // Having extra queues to have seperate up/down transfer queues is more important + score += 4u * extraQueueCount; + notHavingComputeScore *= extraQueueCount; + notHavingGraphicsScore *= extraQueueCount; + } + + if (!hasGraphicsFlag) { + score += notHavingGraphicsScore; + } + + if (!hasComputeFlag) { + score += notHavingComputeScore; + } + + } + + if (score > outFamilyProp.transfer.score) + { + outFamilyProp.transfer.index = familyIndex; + outFamilyProp.transfer.supportsGraphics = hasGraphicsFlag; + outFamilyProp.transfer.supportsCompute = hasComputeFlag; + outFamilyProp.transfer.supportsTransfer = hasTransferFlag; + outFamilyProp.transfer.supportsSparseBinding = hasSparseBindingFlag; + outFamilyProp.transfer.supportsPresent = supportsPresent; + outFamilyProp.transfer.supportsProtected = hasProtectedFlag; + outFamilyProp.transfer.dedicatedQueueCount = extraQueueCount; + outFamilyProp.transfer.score = score; + } + } + assert(extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex); + remainingQueueCounts[extractedInfo.queueFamilyProps.transfer.index] -= extractedInfo.queueFamilyProps.transfer.dedicatedQueueCount; + + // Select Present Queue Family Index + if (!headlessCompute) + { + if (extractedInfo.queueFamilyProps.graphics.supportsPresent && extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex) + { + extractedInfo.queueFamilyProps.present = extractedInfo.queueFamilyProps.graphics; + extractedInfo.queueFamilyProps.present.dedicatedQueueCount = 0u; + } + else + { + const uint32_t maxNeededQueueCountForPresent = 1u; + for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) + { + const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; + auto& outFamilyProp = extractedInfo.queueFamilyProps; + + const uint32_t currentFamilyQueueCount = familyProperty.queueCount; + if (currentFamilyQueueCount <= 0) + continue; + + bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); + bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; + bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; + bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; + bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; + bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; + + const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; + const bool hasEnoughExtraQueues = remainingQueueCount >= 1u; + + /* this will only lead here if selected graphics queue can't support present + * Examples: + * -> score is 0 for every queueFam with no Present support + * -> If both queue families support Present -> "graphics support is preferred rather than extra dedicated queues" + * -> graphics support is equal in scoring to 100 extra queues with no graphics support + * -> If both queue families !hasEnoughExtraQueues -> "graphics support is preferred" + * -> If both queue families hasEnoughExtraQueues and have similar support for graphics -> "queue family with more remainingQueueCount is preferred" + */ + uint32_t score = 0u; + if (supportsPresent) { + score += 1u; + + uint32_t graphicsSupportScore = 100u; + if (hasEnoughExtraQueues) { + score += 1u * remainingQueueCount; + graphicsSupportScore *= remainingQueueCount; + } + + if (hasGraphicsFlag) { + score += graphicsSupportScore; // graphics support is larger in scoring than 100 extra queues with no graphics support + } + } + + if (score > outFamilyProp.present.score) + { + outFamilyProp.present.index = familyIndex; + outFamilyProp.present.supportsGraphics = hasGraphicsFlag; + outFamilyProp.present.supportsCompute = hasComputeFlag; + outFamilyProp.present.supportsTransfer = hasTransferFlag; + outFamilyProp.present.supportsSparseBinding = hasSparseBindingFlag; + outFamilyProp.present.supportsPresent = supportsPresent; + outFamilyProp.present.supportsProtected = hasProtectedFlag; + outFamilyProp.present.dedicatedQueueCount = (hasEnoughExtraQueues) ? 1u : 0u; + outFamilyProp.present.score = score; + } + } + } + assert(extractedInfo.queueFamilyProps.present.index != QueueFamilyProps::InvalidIndex); + remainingQueueCounts[extractedInfo.queueFamilyProps.present.index] -= extractedInfo.queueFamilyProps.present.dedicatedQueueCount; + } + + if (!headlessCompute) + assert(extractedInfo.queueFamilyProps.graphics.supportsTransfer && "This shouldn't happen"); + assert(extractedInfo.queueFamilyProps.compute.supportsTransfer && "This shouldn't happen"); + } + + extractedInfo.isSwapChainSupported = gpu->isSwapchainSupported(); + + // Check if the surface is adequate + if (surface) + { + uint32_t surfaceFormatCount; + surface->getAvailableFormatsForPhysicalDevice(gpu, surfaceFormatCount, nullptr); + extractedInfo.availableSurfaceFormats = std::vector(surfaceFormatCount); + surface->getAvailableFormatsForPhysicalDevice(gpu, surfaceFormatCount, extractedInfo.availableSurfaceFormats.data()); + + extractedInfo.availablePresentModes = surface->getAvailablePresentModesForPhysicalDevice(gpu); + + // TODO: @achal OpenGL shouldn't fail this + extractedInfo.surfaceCapabilities = {}; + if (surface->getSurfaceCapabilitiesForPhysicalDevice(gpu, extractedInfo.surfaceCapabilities)) + extractedInfo.hasSurfaceCapabilities = true; + } + } + + return extractedInfos; +} + +uint32_t CommonAPI::findSuitableGPU(const std::vector& extractedInfos, const bool headlessCompute) +{ + uint32_t ret = ~0u; + for (uint32_t i = 0; i < extractedInfos.size(); ++i) + { + bool isGPUSuitable = false; + const auto& extractedInfo = extractedInfos[i]; + + if (!headlessCompute) + { + if ((extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex) && + (extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex) && + (extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex) && + (extractedInfo.queueFamilyProps.present.index != QueueFamilyProps::InvalidIndex)) + isGPUSuitable = true; + + if (extractedInfo.isSwapChainSupported == false) + isGPUSuitable = false; + + if (extractedInfo.hasSurfaceCapabilities == false) + isGPUSuitable = false; + } + else + { + if ((extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex) && + (extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex)) + isGPUSuitable = true; + } + + if (isGPUSuitable) + { + // find the first suitable GPU + ret = i; + break; + } + } + + if (ret == ~0u) + { + //_NBL_DEBUG_BREAK_IF(true); + ret = 0; + } + + return ret; +} + +nbl::video::ISwapchain::SCreationParams CommonAPI::computeSwapchainCreationParams( + const GPUInfo& gpuInfo, uint32_t& imageCount, + const nbl::core::smart_refctd_ptr& device, + const nbl::core::smart_refctd_ptr& surface, + nbl::asset::IImage::E_USAGE_FLAGS imageUsage, + // Acceptable settings, ordered by preference. + const nbl::asset::E_FORMAT* acceptableSurfaceFormats, uint32_t acceptableSurfaceFormatCount, + const nbl::asset::E_COLOR_PRIMARIES* acceptableColorPrimaries, uint32_t acceptableColorPrimaryCount, + const nbl::asset::ELECTRO_OPTICAL_TRANSFER_FUNCTION* acceptableEotfs, uint32_t acceptableEotfCount, + const nbl::video::ISurface::E_PRESENT_MODE* acceptablePresentModes, uint32_t acceptablePresentModeCount, + const nbl::video::ISurface::E_SURFACE_TRANSFORM_FLAGS* acceptableSurfaceTransforms, uint32_t acceptableSurfaceTransformCount +) +{ + using namespace nbl; + + nbl::video::ISurface::SFormat surfaceFormat; + nbl::video::ISurface::E_PRESENT_MODE presentMode = nbl::video::ISurface::EPM_UNKNOWN; + nbl::video::ISurface::E_SURFACE_TRANSFORM_FLAGS surfaceTransform = nbl::video::ISurface::EST_FLAG_BITS_MAX_ENUM; + + if (device->getAPIType() == nbl::video::EAT_VULKAN) + { + // Deduce format features from imageUsage param + nbl::video::IPhysicalDevice::SFormatImageUsage requiredFormatUsages = {}; + if (imageUsage & asset::IImage::EUF_STORAGE_BIT) + requiredFormatUsages.storageImage = 1; + + nbl::video::ISurface::SCapabilities capabilities; + surface->getSurfaceCapabilitiesForPhysicalDevice(device->getPhysicalDevice(), capabilities); + + for (uint32_t i = 0; i < acceptableSurfaceTransformCount; i++) + { + auto testSurfaceTransform = acceptableSurfaceTransforms[i]; + if (capabilities.currentTransform == testSurfaceTransform) + { + surfaceTransform = testSurfaceTransform; + break; + } + } + assert(surfaceTransform != nbl::video::ISurface::EST_FLAG_BITS_MAX_ENUM); // currentTransform must be supported in acceptableSurfaceTransforms + + auto availablePresentModes = surface->getAvailablePresentModesForPhysicalDevice(device->getPhysicalDevice()); + for (uint32_t i = 0; i < acceptablePresentModeCount; i++) + { + auto testPresentMode = acceptablePresentModes[i]; + if ((availablePresentModes & testPresentMode) == testPresentMode) + { + presentMode = testPresentMode; + break; + } + } + assert(presentMode != nbl::video::ISurface::EST_FLAG_BITS_MAX_ENUM); + + constexpr uint32_t MAX_SURFACE_FORMAT_COUNT = 1000u; + uint32_t availableFormatCount; + nbl::video::ISurface::SFormat availableFormats[MAX_SURFACE_FORMAT_COUNT]; + surface->getAvailableFormatsForPhysicalDevice(device->getPhysicalDevice(), availableFormatCount, availableFormats); + + for (uint32_t i = 0; i < availableFormatCount; ++i) + { + auto testsformat = availableFormats[i]; + bool supportsFormat = false; + bool supportsEotf = false; + bool supportsPrimary = false; + + for (uint32_t i = 0; i < acceptableSurfaceFormatCount; i++) + { + if (testsformat.format == acceptableSurfaceFormats[i]) + { + supportsFormat = true; + break; + } + } + for (uint32_t i = 0; i < acceptableEotfCount; i++) + { + if (testsformat.colorSpace.eotf == acceptableEotfs[i]) + { + supportsEotf = true; + break; + } + } + for (uint32_t i = 0; i < acceptableColorPrimaryCount; i++) + { + if (testsformat.colorSpace.primary == acceptableColorPrimaries[i]) + { + supportsPrimary = true; + break; + } + } + + if (supportsFormat && supportsEotf && supportsPrimary) + { + surfaceFormat = testsformat; + break; + } + } + // Require at least one of the acceptable options to be present + assert(surfaceFormat.format != nbl::asset::EF_UNKNOWN && + surfaceFormat.colorSpace.primary != nbl::asset::ECP_COUNT && + surfaceFormat.colorSpace.eotf != nbl::asset::EOTF_UNKNOWN); + } + else + { + // Temporary path until OpenGL reports properly! + surfaceFormat = nbl::video::ISurface::SFormat(acceptableSurfaceFormats[0], acceptableColorPrimaries[0], acceptableEotfs[0]); + presentMode = nbl::video::ISurface::EPM_IMMEDIATE; + surfaceTransform = nbl::video::ISurface::EST_HORIZONTAL_MIRROR_ROTATE_180_BIT; + } + + nbl::video::ISwapchain::SCreationParams sc_params = {}; + sc_params.arrayLayers = 1u; + sc_params.minImageCount = imageCount; + sc_params.presentMode = presentMode; + sc_params.imageUsage = imageUsage; + sc_params.surface = surface; + sc_params.preTransform = surfaceTransform; + sc_params.compositeAlpha = nbl::video::ISurface::ECA_OPAQUE_BIT; + sc_params.surfaceFormat = surfaceFormat; + + return sc_params; +} + +void CommonAPI::dropRetiredSwapchainResources(nbl::core::deque& qRetiredSwapchainResources, const uint64_t completedFrameId) +{ + while (!qRetiredSwapchainResources.empty() && qRetiredSwapchainResources.front()->retiredFrameId < completedFrameId) + { + std::cout << "Dropping resource scheduled at " << qRetiredSwapchainResources.front()->retiredFrameId << " with completedFrameId " << completedFrameId << "\n"; + delete(qRetiredSwapchainResources.front()); + qRetiredSwapchainResources.pop_front(); + } +} + +void CommonAPI::retireSwapchainResources(nbl::core::deque& qRetiredSwapchainResources, IRetiredSwapchainResources* retired) +{ + qRetiredSwapchainResources.push_back(retired); +} + +nbl::core::smart_refctd_ptr CommonAPI::createRenderpass(const nbl::core::smart_refctd_ptr& device, nbl::asset::E_FORMAT colorAttachmentFormat, nbl::asset::E_FORMAT baseDepthFormat) +{ + using namespace nbl; + + bool useDepth = baseDepthFormat != nbl::asset::EF_UNKNOWN; + nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN; + if (useDepth) + { + depthFormat = device->getPhysicalDevice()->promoteImageFormat( + { baseDepthFormat, nbl::video::IPhysicalDevice::SFormatImageUsage(nbl::asset::IImage::EUF_DEPTH_STENCIL_ATTACHMENT_BIT) }, + nbl::video::IGPUImage::ET_OPTIMAL + ); + assert(depthFormat != nbl::asset::EF_UNKNOWN); + } + + nbl::video::IGPURenderpass::SCreationParams::SAttachmentDescription attachments[2]; + attachments[0].initialLayout = asset::IImage::EL_UNDEFINED; + attachments[0].finalLayout = asset::IImage::EL_PRESENT_SRC; + attachments[0].format = colorAttachmentFormat; + attachments[0].samples = asset::IImage::ESCF_1_BIT; + attachments[0].loadOp = nbl::video::IGPURenderpass::ELO_CLEAR; + attachments[0].storeOp = nbl::video::IGPURenderpass::ESO_STORE; + + attachments[1].initialLayout = asset::IImage::EL_UNDEFINED; + attachments[1].finalLayout = asset::IImage::EL_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].format = depthFormat; + attachments[1].samples = asset::IImage::ESCF_1_BIT; + attachments[1].loadOp = nbl::video::IGPURenderpass::ELO_CLEAR; + attachments[1].storeOp = nbl::video::IGPURenderpass::ESO_STORE; + + nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription::SAttachmentRef colorAttRef; + colorAttRef.attachment = 0u; + colorAttRef.layout = asset::IImage::EL_COLOR_ATTACHMENT_OPTIMAL; + + nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription::SAttachmentRef depthStencilAttRef; + depthStencilAttRef.attachment = 1u; + depthStencilAttRef.layout = asset::IImage::EL_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription sp; + sp.pipelineBindPoint = asset::EPBP_GRAPHICS; + sp.colorAttachmentCount = 1u; + sp.colorAttachments = &colorAttRef; + if (useDepth) { + sp.depthStencilAttachment = &depthStencilAttRef; + } + else { + sp.depthStencilAttachment = nullptr; + } + sp.flags = nbl::video::IGPURenderpass::ESDF_NONE; + sp.inputAttachmentCount = 0u; + sp.inputAttachments = nullptr; + sp.preserveAttachmentCount = 0u; + sp.preserveAttachments = nullptr; + sp.resolveAttachments = nullptr; + + nbl::video::IGPURenderpass::SCreationParams rp_params; + rp_params.attachmentCount = (useDepth) ? 2u : 1u; + rp_params.attachments = attachments; + rp_params.dependencies = nullptr; + rp_params.dependencyCount = 0u; + rp_params.subpasses = &sp; + rp_params.subpassCount = 1u; + + return device->createRenderpass(rp_params); +} + +nbl::core::smart_refctd_dynamic_array> CommonAPI::createFBOWithSwapchainImages( + size_t imageCount, uint32_t width, uint32_t height, + const nbl::core::smart_refctd_ptr& device, + nbl::core::smart_refctd_ptr swapchain, + nbl::core::smart_refctd_ptr renderpass, + nbl::asset::E_FORMAT baseDepthFormat +) { + using namespace nbl; + + bool useDepth = baseDepthFormat != nbl::asset::EF_UNKNOWN; + nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN; + if (useDepth) + { + depthFormat = baseDepthFormat; + //depthFormat = device->getPhysicalDevice()->promoteImageFormat( + // { baseDepthFormat, nbl::video::IPhysicalDevice::SFormatImageUsage(nbl::asset::IImage::EUF_DEPTH_STENCIL_ATTACHMENT_BIT) }, + // nbl::asset::IImage::ET_OPTIMAL + //); + // TODO error reporting + assert(depthFormat != nbl::asset::EF_UNKNOWN); + } + + auto fbo = core::make_refctd_dynamic_array>>(imageCount); + for (uint32_t i = 0u; i < imageCount; ++i) + { + nbl::core::smart_refctd_ptr view[2] = {}; + + auto img = swapchain->createImage(i); + { + nbl::video::IGPUImageView::SCreationParams view_params; + view_params.format = img->getCreationParameters().format; + view_params.viewType = asset::IImageView::ET_2D; + view_params.subresourceRange.aspectMask = asset::IImage::EAF_COLOR_BIT; + view_params.subresourceRange.baseMipLevel = 0u; + view_params.subresourceRange.levelCount = 1u; + view_params.subresourceRange.baseArrayLayer = 0u; + view_params.subresourceRange.layerCount = 1u; + view_params.image = std::move(img); + + view[0] = device->createImageView(std::move(view_params)); + assert(view[0]); + } + + if (useDepth) { + nbl::video::IGPUImage::SCreationParams imgParams; + imgParams.flags = static_cast(0u); + imgParams.type = asset::IImage::ET_2D; + imgParams.format = depthFormat; + imgParams.extent = { width, height, 1 }; + imgParams.usage = asset::IImage::E_USAGE_FLAGS::EUF_DEPTH_STENCIL_ATTACHMENT_BIT; + imgParams.mipLevels = 1u; + imgParams.arrayLayers = 1u; + imgParams.samples = asset::IImage::ESCF_1_BIT; + + auto depthImg = device->createImage(std::move(imgParams)); + auto depthImgMemReqs = depthImg->getMemoryReqs(); + depthImgMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); + auto depthImgMem = device->allocate(depthImgMemReqs, depthImg.get()); + + nbl::video::IGPUImageView::SCreationParams view_params; + view_params.format = depthFormat; + view_params.viewType = asset::IImageView::ET_2D; + view_params.subresourceRange.aspectMask = asset::IImage::EAF_DEPTH_BIT; + view_params.subresourceRange.baseMipLevel = 0u; + view_params.subresourceRange.levelCount = 1u; + view_params.subresourceRange.baseArrayLayer = 0u; + view_params.subresourceRange.layerCount = 1u; + view_params.image = std::move(depthImg); + + view[1] = device->createImageView(std::move(view_params)); + assert(view[1]); + } + + nbl::video::IGPUFramebuffer::SCreationParams fb_params; + fb_params.width = width; + fb_params.height = height; + fb_params.layers = 1u; + fb_params.renderpass = renderpass; + fb_params.flags = static_cast(0); + fb_params.attachmentCount = (useDepth) ? 2u : 1u; + fb_params.attachments = view; + + fbo->begin()[i] = device->createFramebuffer(std::move(fb_params)); + assert(fbo->begin()[i]); + } + return fbo; +} + +bool CommonAPI::createSwapchain( + const nbl::core::smart_refctd_ptr&& device, + nbl::video::ISwapchain::SCreationParams& params, + uint32_t width, uint32_t height, + // nullptr for initial creation, old swapchain for eventual resizes + nbl::core::smart_refctd_ptr& swapchain +) +{ + auto oldSwapchain = swapchain; + + nbl::video::ISwapchain::SCreationParams paramsCp = params; + paramsCp.width = width; + paramsCp.height = height; + paramsCp.oldSwapchain = oldSwapchain; + + if (device->getAPIType() == nbl::video::EAT_VULKAN) + { + swapchain = nbl::video::CVulkanSwapchain::create(std::move(device), std::move(paramsCp)); + } + else if (device->getAPIType() == nbl::video::EAT_OPENGL) + { + swapchain = nbl::video::COpenGLSwapchain::create(std::move(device), std::move(paramsCp)); + } + else if (device->getAPIType() == nbl::video::EAT_OPENGL_ES) + { + swapchain = nbl::video::COpenGLESSwapchain::create(std::move(device), std::move(paramsCp)); + } + else + { + _NBL_TODO(); + } + + assert(swapchain); + assert(swapchain != oldSwapchain); + + return true; +} + +void CommonAPI::performGpuInit(InitParams& params, InitOutput& result) +{ + using namespace nbl; + using namespace nbl::video; + + bool headlessCompute = params.isHeadlessCompute(); + + if (params.apiType == EAT_VULKAN) + { + auto _apiConnection = nbl::video::CVulkanConnection::create( + nbl::core::smart_refctd_ptr(result.system), + 0, + params.appName.data(), + params.requiredInstanceFeatures.count, + params.requiredInstanceFeatures.features, + params.optionalInstanceFeatures.count, + params.optionalInstanceFeatures.features, + nbl::core::smart_refctd_ptr(result.logger), + true); + + if (!headlessCompute) + { +#ifdef _NBL_PLATFORM_WINDOWS_ + result.surface = nbl::video::CSurfaceVulkanWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#elif defined(_NBL_PLATFORM_ANDROID_) + ////result.surface = nbl::video::CSurfaceVulkanAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#endif + } + result.apiConnection = _apiConnection; + } + else if (params.apiType == EAT_OPENGL) + { + auto _apiConnection = nbl::video::COpenGLConnection::create(nbl::core::smart_refctd_ptr(result.system), 0, params.appName.data(), nbl::video::COpenGLDebugCallback(nbl::core::smart_refctd_ptr(result.logger))); + + if (!headlessCompute) + { +#ifdef _NBL_PLATFORM_WINDOWS_ + result.surface = nbl::video::CSurfaceGLWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#elif defined(_NBL_PLATFORM_ANDROID_) + result.surface = nbl::video::CSurfaceGLAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#endif + } + + result.apiConnection = _apiConnection; + } + else if (params.apiType == EAT_OPENGL_ES) + { + auto _apiConnection = nbl::video::COpenGLESConnection::create(nbl::core::smart_refctd_ptr(result.system), 0, params.appName.data(), nbl::video::COpenGLDebugCallback(nbl::core::smart_refctd_ptr(result.logger))); + + if (!headlessCompute) + { +#ifdef _NBL_PLATFORM_WINDOWS_ + result.surface = nbl::video::CSurfaceGLWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#elif defined(_NBL_PLATFORM_ANDROID_) + result.surface = nbl::video::CSurfaceGLAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(params.window.get()))); +#endif + } + + result.apiConnection = _apiConnection; + } + else + { + _NBL_TODO(); + } + + auto gpus = result.apiConnection->getPhysicalDevices(); + assert(!gpus.empty()); + auto extractedInfos = extractGPUInfos(gpus, result.surface, headlessCompute); + auto suitableGPUIndex = findSuitableGPU(extractedInfos, headlessCompute); + auto gpu = gpus.begin()[suitableGPUIndex]; + const auto& gpuInfo = extractedInfos[suitableGPUIndex]; + + // Fill QueueCreationParams + constexpr uint32_t MaxQueuesInFamily = 32; + float queuePriorities[MaxQueuesInFamily]; + std::fill(queuePriorities, queuePriorities + MaxQueuesInFamily, IGPUQueue::DEFAULT_QUEUE_PRIORITY); + + constexpr uint32_t MaxQueueFamilyCount = 4; + nbl::video::ILogicalDevice::SQueueCreationParams qcp[MaxQueueFamilyCount] = {}; + + uint32_t actualQueueParamsCount = 0u; + + uint32_t queuesIndexInFamily[InitOutput::EQT_COUNT]; + uint32_t presentQueueIndexInFamily = 0u; + + // Graphics Queue + if (!headlessCompute) + { + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.graphics.dedicatedQueueCount; + assert(dedicatedQueuesInFamily >= 1u); + + qcp[0].familyIndex = gpuInfo.queueFamilyProps.graphics.index; + qcp[0].count = dedicatedQueuesInFamily; + qcp[0].flags = static_cast(0); + qcp[0].priorities = queuePriorities; + queuesIndexInFamily[InitOutput::EQT_GRAPHICS] = 0u; + actualQueueParamsCount++; + } + + // Compute Queue + bool foundComputeInOtherFamily = false; + for (uint32_t i = 0; i < actualQueueParamsCount; ++i) + { + auto& otherQcp = qcp[i]; + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.compute.dedicatedQueueCount; + if (otherQcp.familyIndex == gpuInfo.queueFamilyProps.compute.index) + { + if (dedicatedQueuesInFamily >= 1) + { + queuesIndexInFamily[InitOutput::EQT_COMPUTE] = otherQcp.count + 0u; + } + else + { + queuesIndexInFamily[InitOutput::EQT_COMPUTE] = 0u; + } + otherQcp.count += dedicatedQueuesInFamily; + foundComputeInOtherFamily = true; + break; // If works correctly no need to check other family indices as they are unique + } + } + if (!foundComputeInOtherFamily) + { + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.compute.dedicatedQueueCount; + assert(dedicatedQueuesInFamily == 1u); + + queuesIndexInFamily[InitOutput::EQT_COMPUTE] = 0u; + + auto& computeQcp = qcp[actualQueueParamsCount]; + computeQcp.familyIndex = gpuInfo.queueFamilyProps.compute.index; + computeQcp.count = dedicatedQueuesInFamily; + computeQcp.flags = static_cast(0); + computeQcp.priorities = queuePriorities; + actualQueueParamsCount++; + } + + // Transfer Queue + bool foundTransferInOtherFamily = false; + for (uint32_t i = 0; i < actualQueueParamsCount; ++i) + { + auto& otherQcp = qcp[i]; + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.transfer.dedicatedQueueCount; + if (otherQcp.familyIndex == gpuInfo.queueFamilyProps.transfer.index) + { + if (dedicatedQueuesInFamily >= 2u) + { + queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = otherQcp.count + 0u; + queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = otherQcp.count + 1u; + } + else if (dedicatedQueuesInFamily >= 1u) + { + queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = otherQcp.count + 0u; + queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = otherQcp.count + 0u; + } + else if (dedicatedQueuesInFamily == 0u) + { + queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; + queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 0u; + } + otherQcp.count += dedicatedQueuesInFamily; + foundTransferInOtherFamily = true; + break; // If works correctly no need to check other family indices as they are unique + } + } + if (!foundTransferInOtherFamily) + { + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.transfer.dedicatedQueueCount; + assert(dedicatedQueuesInFamily >= 1u); + + if (dedicatedQueuesInFamily >= 2u) + { + queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; + queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 1u; + } + else if (dedicatedQueuesInFamily >= 1u) + { + queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; + queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 0u; + } + else + { + assert(false); + } + + auto& transferQcp = qcp[actualQueueParamsCount]; + transferQcp.familyIndex = gpuInfo.queueFamilyProps.transfer.index; + transferQcp.count = dedicatedQueuesInFamily; + transferQcp.flags = static_cast(0); + transferQcp.priorities = queuePriorities; + actualQueueParamsCount++; + } + + // Present Queue + if (!headlessCompute) + { + bool foundPresentInOtherFamily = false; + for (uint32_t i = 0; i < actualQueueParamsCount; ++i) + { + auto& otherQcp = qcp[i]; + if (otherQcp.familyIndex == gpuInfo.queueFamilyProps.present.index) + { + if (otherQcp.familyIndex == gpuInfo.queueFamilyProps.graphics.index) + { + presentQueueIndexInFamily = 0u; + } + else + { + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.present.dedicatedQueueCount; + + if (dedicatedQueuesInFamily >= 1u) + { + presentQueueIndexInFamily = otherQcp.count + 0u; + } + else if (dedicatedQueuesInFamily == 0u) + { + presentQueueIndexInFamily = 0u; + } + otherQcp.count += dedicatedQueuesInFamily; + } + foundPresentInOtherFamily = true; + break; // If works correctly no need to check other family indices as they are unique + } + } + if (!foundPresentInOtherFamily) + { + uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.present.dedicatedQueueCount; + assert(dedicatedQueuesInFamily == 1u); + presentQueueIndexInFamily = 0u; + + auto& presentQcp = qcp[actualQueueParamsCount]; + presentQcp.familyIndex = gpuInfo.queueFamilyProps.present.index; + presentQcp.count = dedicatedQueuesInFamily; + presentQcp.flags = static_cast(0); + presentQcp.priorities = queuePriorities; + actualQueueParamsCount++; + } + } + + nbl::video::ILogicalDevice::SCreationParams dev_params; + dev_params.queueParamsCount = actualQueueParamsCount; + dev_params.queueParams = qcp; + dev_params.requiredFeatureCount = params.requiredDeviceFeatures.count; + dev_params.requiredFeatures = params.requiredDeviceFeatures.features; + dev_params.optionalFeatureCount = params.optionalDeviceFeatures.count; + dev_params.optionalFeatures = params.optionalDeviceFeatures.features; + result.logicalDevice = gpu->createLogicalDevice(dev_params); + + result.utilities = nbl::core::make_smart_refctd_ptr(nbl::core::smart_refctd_ptr(result.logicalDevice)); + + if (!headlessCompute) + result.queues[InitOutput::EQT_GRAPHICS] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, queuesIndexInFamily[InitOutput::EQT_GRAPHICS]); + result.queues[InitOutput::EQT_COMPUTE] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); + + // TEMP_FIX +#ifdef EXAMPLES_CAN_HANDLE_TRANSFER_WITHOUT_GRAPHICS + result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.transfer.index, queuesIndexInFamily[EQT_TRANSFER_UP]); + result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.transfer.index, queuesIndexInFamily[EQT_TRANSFER_DOWN]); +#else + if (!headlessCompute) + { + result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, 0u); + result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, 0u); + } + else + { + result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); + result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); + } +#endif + if (!headlessCompute) + { + + result.swapchainCreationParams = computeSwapchainCreationParams( + gpuInfo, + params.swapchainImageCount, + result.logicalDevice, + result.surface, + params.swapchainImageUsage, + params.acceptableSurfaceFormats, params.acceptableSurfaceFormatCount, + params.acceptableColorPrimaries, params.acceptableColorPrimaryCount, + params.acceptableEotfs, params.acceptableEotfCount, + params.acceptablePresentModes, params.acceptablePresentModeCount, + params.acceptableSurfaceTransforms, params.acceptableSurfaceTransformCount + ); + + nbl::asset::E_FORMAT swapChainFormat = result.swapchainCreationParams.surfaceFormat.format; + result.renderToSwapchainRenderpass = createRenderpass(result.logicalDevice, swapChainFormat, params.depthFormat); + } + + uint32_t commandPoolsToCreate = core::max(params.framesInFlight, 1u); + for (uint32_t i = 0; i < InitOutput::EQT_COUNT; ++i) + { + const IGPUQueue* queue = result.queues[i]; + if (queue != nullptr) + { + for (size_t j = 0; j < commandPoolsToCreate; j++) + { + result.commandPools[i][j] = result.logicalDevice->createCommandPool(queue->getFamilyIndex(), IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); + assert(result.commandPools[i][j]); + } + } + } + + result.physicalDevice = gpu; + + uint32_t mainQueueFamilyIndex = (headlessCompute) ? gpuInfo.queueFamilyProps.compute.index : gpuInfo.queueFamilyProps.graphics.index; + result.cpu2gpuParams.assetManager = result.assetManager.get(); + result.cpu2gpuParams.device = result.logicalDevice.get(); + result.cpu2gpuParams.finalQueueFamIx = mainQueueFamilyIndex; + result.cpu2gpuParams.limits = result.physicalDevice->getLimits(); + result.cpu2gpuParams.pipelineCache = nullptr; + result.cpu2gpuParams.utilities = result.utilities.get(); + + result.cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_TRANSFER].queue = result.queues[InitOutput::EQT_TRANSFER_UP]; + result.cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_COMPUTE].queue = result.queues[InitOutput::EQT_COMPUTE]; + + const uint32_t transferUpQueueFamIndex = result.queues[InitOutput::EQT_TRANSFER_UP]->getFamilyIndex(); + const uint32_t computeQueueFamIndex = result.queues[InitOutput::EQT_COMPUTE]->getFamilyIndex(); + + auto pool_transfer = result.logicalDevice->createCommandPool(transferUpQueueFamIndex, IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); + nbl::core::smart_refctd_ptr pool_compute; + if (transferUpQueueFamIndex == computeQueueFamIndex) + pool_compute = pool_transfer; + else + pool_compute = result.logicalDevice->createCommandPool(result.queues[InitOutput::EQT_COMPUTE]->getFamilyIndex(), IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); + + nbl::core::smart_refctd_ptr transferCmdBuffer; + nbl::core::smart_refctd_ptr computeCmdBuffer; + + result.logicalDevice->createCommandBuffers(pool_transfer.get(), IGPUCommandBuffer::EL_PRIMARY, 1u, &transferCmdBuffer); + result.logicalDevice->createCommandBuffers(pool_compute.get(), IGPUCommandBuffer::EL_PRIMARY, 1u, &computeCmdBuffer); + + result.cpu2gpuParams.perQueue[IGPUObjectFromAssetConverter::EQU_TRANSFER].cmdbuf = transferCmdBuffer; + result.cpu2gpuParams.perQueue[IGPUObjectFromAssetConverter::EQU_COMPUTE].cmdbuf = computeCmdBuffer; +} diff --git a/common/CommonAPI.h b/common/CommonAPI.h index 32023bf42..092116d8c 100644 --- a/common/CommonAPI.h +++ b/common/CommonAPI.h @@ -1,8 +1,12 @@ +#ifndef __NBL_COMMON_API_H_INCLUDED__ +#define __NBL_COMMON_API_H_INCLUDED__ + #define _NBL_STATIC_LIB_ #include // TODO: get these all included by the appropriate namespace headers! #include "nbl/system/IApplicationFramework.h" +#include "nbl/video/IDeviceMemoryBacked.h" #include "nbl/ui/CGraphicalApplicationAndroid.h" #include "nbl/ui/CWindowManagerAndroid.h" #include "nbl/ui/IGraphicalApplicationFramework.h" @@ -16,14 +20,10 @@ #include "nbl/system/CSystemWin32.h" // TODO: make these include themselves via `nabla.h` - - - class CommonAPI { CommonAPI() = delete; -public: - +public: class CommonAPIEventCallback; class InputSystem : public nbl::core::IReferenceCounted @@ -204,90 +204,19 @@ class CommonAPI Channels m_keyboard; }; - // TODO: can you guys just use one callback!? class ICommonAPIEventCallback : public nbl::ui::IWindow::IEventCallback { public: virtual void setLogger(nbl::system::logger_opt_smart_ptr& logger) = 0; - }; - class CTemporaryEventCallback : public ICommonAPIEventCallback - { - nbl::system::logger_opt_smart_ptr m_logger = nullptr; - public: - void setLogger(nbl::system::logger_opt_smart_ptr& logger) override - { - m_logger = logger; - } - private: - bool onWindowShown_impl() override - { - m_logger.log("Window Shown"); - return true; - } - bool onWindowHidden_impl() override - { - m_logger.log("Window hidden"); - return true; - } - bool onWindowMoved_impl(int32_t x, int32_t y) override - { - m_logger.log("Window window moved to { %d, %d }", nbl::system::ILogger::ELL_WARNING, x, y); - return true; - } - bool onWindowResized_impl(uint32_t w, uint32_t h) override - { - m_logger.log("Window resized to { %u, %u }", nbl::system::ILogger::ELL_DEBUG, w, h); - return true; - } - bool onWindowMinimized_impl() override - { - m_logger.log("Window minimized", nbl::system::ILogger::ELL_ERROR); - return true; - } - bool onWindowMaximized_impl() override - { - m_logger.log("Window maximized", nbl::system::ILogger::ELL_PERFORMANCE); - return true; - } - void onGainedMouseFocus_impl() override - { - m_logger.log("Window gained mouse focus", nbl::system::ILogger::ELL_INFO); - } - void onLostMouseFocus_impl() override - { - m_logger.log("Window lost mouse focus", nbl::system::ILogger::ELL_INFO); - } - void onGainedKeyboardFocus_impl() override - { - m_logger.log("Window gained keyboard focus", nbl::system::ILogger::ELL_INFO); - } - void onLostKeyboardFocus_impl() override - { - m_logger.log("Window lost keyboard focus", nbl::system::ILogger::ELL_INFO); - } - void onMouseConnected_impl(nbl::core::smart_refctd_ptr&& mch) override - { - m_logger.log("A mouse has been connected", nbl::system::ILogger::ELL_INFO); - } - void onMouseDisconnected_impl(nbl::ui::IMouseEventChannel* mch) override - { - m_logger.log("A mouse has been disconnected", nbl::system::ILogger::ELL_INFO); - } - void onKeyboardConnected_impl(nbl::core::smart_refctd_ptr&& kbch) override - { - m_logger.log("A keyboard has been connected", nbl::system::ILogger::ELL_INFO); - } - void onKeyboardDisconnected_impl(nbl::ui::IKeyboardEventChannel* kbch) override - { - m_logger.log("A keyboard has been disconnected", nbl::system::ILogger::ELL_INFO); - } - bool onWindowClosed_impl() override + void setApplication(nbl::ui::IGraphicalApplicationFramework* app) { - m_logger.log("Window closed"); - return true; + m_app = std::move(app); } + protected: + nbl::ui::IGraphicalApplicationFramework* m_app = nullptr; }; + class CommonAPIEventCallback : public ICommonAPIEventCallback { public: @@ -321,6 +250,7 @@ class CommonAPI bool onWindowResized_impl(uint32_t w, uint32_t h) override { m_logger.log("Window resized to { %u, %u }", nbl::system::ILogger::ELL_DEBUG, w, h); + if (m_app) m_app->onResize(w, h); return true; } bool onWindowMinimized_impl() override @@ -435,375 +365,65 @@ class CommonAPI static std::vector extractGPUInfos( nbl::core::SRange gpus, nbl::core::smart_refctd_ptr surface, - const bool headlessCompute = false) - { - using namespace nbl; - using namespace nbl::video; - - std::vector extractedInfos = std::vector(gpus.size()); - - for (size_t i = 0ull; i < gpus.size(); ++i) - { - auto& extractedInfo = extractedInfos[i]; - extractedInfo = {}; - auto gpu = gpus.begin()[i]; - - // Find queue family indices - { - const auto& queueFamilyProperties = gpu->getQueueFamilyProperties(); - - std::vector remainingQueueCounts = std::vector(queueFamilyProperties.size(), 0u); - - for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) - { - const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; - remainingQueueCounts[familyIndex] = familyProperty.queueCount; - } - - // Select Graphics Queue Family Index - if(!headlessCompute) - { - // Select Graphics Queue Family Index - for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) - { - const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; - auto& outFamilyProp = extractedInfo.queueFamilyProps; - - const uint32_t currentFamilyQueueCount = familyProperty.queueCount; - if(currentFamilyQueueCount <= 0) - continue; - - bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); - bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; - bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; - bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; - bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; - bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; - - const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; - const bool hasEnoughQueues = remainingQueueCount >= 1u; - - /* - * Examples: - * -> score is 0 for every queueFam with no Graphics support - * -> If both queue families !hasEnoughtQueues -> score will be equal but this doesn't/shouldn't happen -> there should be a queueFamily with "enoughQueues" for graphics. - * -> if both queue families hasEnoughQueues and have similar support for present and compute: Queue Family with more remainingQueueCount is preferred. - * -> if both queue families hasEnoughQueues with the same number of remainingQueueCount -> "QueueFamily with present and no compute" >>>> "QueueFamily with compute and no present" - * -> if both queue families hasEnoughQueues -> "QueueFamily with compute and no present and 16 remainingQueues" ==== "QueueFamily with present and no compute and 1 remaining Queue" - * -> if both queue families hasEnoughQueues -> "QueueFamily with present and compute and 1 remaining Queue" ==== "QueueFamily with no compute and no present and 34 remaining Queues xD" - */ - uint32_t score = 0u; - if(hasGraphicsFlag) { - score++; - if(hasEnoughQueues) { - score += 1u * remainingQueueCount; - - if(supportsPresent) - { - score += 32u; // more important to have present than compute (presentSupport is larger in scoring to 16 extra compute queues) - } - - if(hasComputeFlag) - { - score += 1u * remainingQueueCount; - } - } - } - - if(score > outFamilyProp.graphics.score) - { - outFamilyProp.graphics.index = familyIndex; - outFamilyProp.graphics.supportsGraphics = hasGraphicsFlag; - outFamilyProp.graphics.supportsCompute = hasComputeFlag; - outFamilyProp.graphics.supportsTransfer = true; // Reporting this is optional for Vk Graphics-Capable QueueFam, but Its support is guaranteed. - outFamilyProp.graphics.supportsSparseBinding = hasSparseBindingFlag; - outFamilyProp.graphics.supportsPresent = supportsPresent; - outFamilyProp.graphics.supportsProtected = hasProtectedFlag; - outFamilyProp.graphics.dedicatedQueueCount = 1u; - outFamilyProp.graphics.score = score; - } - } - assert(extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex); - remainingQueueCounts[extractedInfo.queueFamilyProps.graphics.index] -= extractedInfo.queueFamilyProps.graphics.dedicatedQueueCount; - } - - // Select Compute Queue Family Index - for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) - { - const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; - auto& outFamilyProp = extractedInfo.queueFamilyProps; - - const uint32_t currentFamilyQueueCount = familyProperty.queueCount; - if(currentFamilyQueueCount <= 0) - continue; - - bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); - bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; - bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; - bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; - bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; - bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; - - const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; - const bool hasExtraQueues = remainingQueueCount >= 1u; - - /* - * Examples: - * -> If both !hasEnoughExtraQueues: "queue family that supports graphics" >>>> "queue family that doesn't support graphics" - * -> If both queueFams supports Graphics and hasEnoughExtraQueues: "Graphics-capable QueueFamily equal to the selected Graphics QueueFam" >>>> "Any other Graphics-capable QueueFamily" - * -> If both support Graphics (not equal to graphicsQueueFamIndex): "queue family that hasEnoughExtraQueues" >>>> "queue family that !hasEnoughExtraQueues" - * -> If both support Graphics and hasEnoughExtraQueues (not equal to graphicsQueueFamIndex): both are adequate enough, depends on the order of the queueFams. - * -> "Compute-capable QueueFam with hasEnoughExtraQueues" >>>> "Compute-capable QueueFam with graphics capability and ==graphicsQueueFamIdx with no extra dedicated queues" - */ - uint32_t score = 0u; - if(hasComputeFlag) { - score++; - - if(hasExtraQueues) { - score += 3; - } - - if(!headlessCompute && hasGraphicsFlag) { - score++; - if(familyIndex == outFamilyProp.graphics.index) { - score++; - } - } - } - - if(score > outFamilyProp.compute.score) - { - outFamilyProp.compute.index = familyIndex; - outFamilyProp.compute.supportsGraphics = hasGraphicsFlag; - outFamilyProp.compute.supportsCompute = hasComputeFlag; - outFamilyProp.compute.supportsTransfer = true; // Reporting this is optional for Vk Compute-Capable QueueFam, but Its support is guaranteed. - outFamilyProp.compute.supportsSparseBinding = hasSparseBindingFlag; - outFamilyProp.compute.supportsPresent = supportsPresent; - outFamilyProp.compute.supportsProtected = hasProtectedFlag; - outFamilyProp.compute.dedicatedQueueCount = (hasExtraQueues) ? 1u : 0u; - outFamilyProp.compute.score = score; - } - } - assert(extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex); - remainingQueueCounts[extractedInfo.queueFamilyProps.compute.index] -= extractedInfo.queueFamilyProps.compute.dedicatedQueueCount; - - // Select Transfer Queue Family Index - for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) - { - const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; - auto& outFamilyProp = extractedInfo.queueFamilyProps; - - const uint32_t currentFamilyQueueCount = familyProperty.queueCount; - if(currentFamilyQueueCount <= 0) - continue; - - bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); - bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; - bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; - bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; - bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; - bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; - - const uint32_t extraQueueCount = nbl::core::min(remainingQueueCounts[familyIndex], 2u); // UP + DOWN - const bool hasExtraQueues = extraQueueCount >= 1u; - - /* - * Examples: - * -> score is 0 for every queueFam with no Transfer support - * -> If both have similar hasEnoughExtraQueues, compute and graphics support: the one with more remainingQueueCount is preferred - * -> If both support Transfer: "QueueFam with >=1 extra queues and graphics and compute support" >>>> (less probable)"QueueFam with no extra queues and transfer-only(no compute and graphics support)" - * -> If both support Transfer: "QueueFam with >=0 extra queues and only compute" >>>> "QueueFam with >=0 extra queues and only graphics" - */ - uint32_t score = 0u; - if(hasTransferFlag) { - score += 1u; - - uint32_t notHavingComputeScore = 1u; - uint32_t notHavingGraphicsScore = 2u; - - if(hasExtraQueues) { // Having extra queues to have seperate up/down transfer queues is more important - score += 4u * extraQueueCount; - notHavingComputeScore *= extraQueueCount; - notHavingGraphicsScore *= extraQueueCount; - } - - if(!hasGraphicsFlag) { - score += notHavingGraphicsScore; - } - - if(!hasComputeFlag) { - score += notHavingComputeScore; - } - - } - - if(score > outFamilyProp.transfer.score) - { - outFamilyProp.transfer.index = familyIndex; - outFamilyProp.transfer.supportsGraphics = hasGraphicsFlag; - outFamilyProp.transfer.supportsCompute = hasComputeFlag; - outFamilyProp.transfer.supportsTransfer = hasTransferFlag; - outFamilyProp.transfer.supportsSparseBinding = hasSparseBindingFlag; - outFamilyProp.transfer.supportsPresent = supportsPresent; - outFamilyProp.transfer.supportsProtected = hasProtectedFlag; - outFamilyProp.transfer.dedicatedQueueCount = extraQueueCount; - outFamilyProp.transfer.score = score; - } - } - assert(extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex); - remainingQueueCounts[extractedInfo.queueFamilyProps.transfer.index] -= extractedInfo.queueFamilyProps.transfer.dedicatedQueueCount; - - // Select Present Queue Family Index - if(!headlessCompute) - { - if(extractedInfo.queueFamilyProps.graphics.supportsPresent && extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex) - { - extractedInfo.queueFamilyProps.present = extractedInfo.queueFamilyProps.graphics; - extractedInfo.queueFamilyProps.present.dedicatedQueueCount = 0u; - } - else - { - const uint32_t maxNeededQueueCountForPresent = 1u; - for (uint32_t familyIndex = 0u; familyIndex < queueFamilyProperties.size(); ++familyIndex) - { - const auto& familyProperty = queueFamilyProperties.begin()[familyIndex]; - auto& outFamilyProp = extractedInfo.queueFamilyProps; - - const uint32_t currentFamilyQueueCount = familyProperty.queueCount; - if(currentFamilyQueueCount <= 0) - continue; - - bool supportsPresent = surface && surface->isSupportedForPhysicalDevice(gpu, familyIndex); - bool hasGraphicsFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_GRAPHICS_BIT).value != 0; - bool hasComputeFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_COMPUTE_BIT).value != 0; - bool hasTransferFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_TRANSFER_BIT).value != 0; - bool hasSparseBindingFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_SPARSE_BINDING_BIT).value != 0; - bool hasProtectedFlag = (familyProperty.queueFlags & IPhysicalDevice::EQF_PROTECTED_BIT).value != 0; - - const uint32_t remainingQueueCount = remainingQueueCounts[familyIndex]; - const bool hasEnoughExtraQueues = remainingQueueCount >= 1u; - - /* this will only lead here if selected graphics queue can't support present - * Examples: - * -> score is 0 for every queueFam with no Present support - * -> If both queue families support Present -> "graphics support is preferred rather than extra dedicated queues" - * -> graphics support is equal in scoring to 100 extra queues with no graphics support - * -> If both queue families !hasEnoughExtraQueues -> "graphics support is preferred" - * -> If both queue families hasEnoughExtraQueues and have similar support for graphics -> "queue family with more remainingQueueCount is preferred" - */ - uint32_t score = 0u; - if(supportsPresent) { - score += 1u; - - uint32_t graphicsSupportScore = 100u; - if(hasEnoughExtraQueues) { - score += 1u * remainingQueueCount; - graphicsSupportScore *= remainingQueueCount; - } - - if(hasGraphicsFlag) { - score += graphicsSupportScore; // graphics support is larger in scoring than 100 extra queues with no graphics support - } - } - - if(score > outFamilyProp.present.score) - { - outFamilyProp.present.index = familyIndex; - outFamilyProp.present.supportsGraphics = hasGraphicsFlag; - outFamilyProp.present.supportsCompute = hasComputeFlag; - outFamilyProp.present.supportsTransfer = hasTransferFlag; - outFamilyProp.present.supportsSparseBinding = hasSparseBindingFlag; - outFamilyProp.present.supportsPresent = supportsPresent; - outFamilyProp.present.supportsProtected = hasProtectedFlag; - outFamilyProp.present.dedicatedQueueCount = (hasEnoughExtraQueues) ? 1u : 0u; - outFamilyProp.present.score = score; - } - } - } - assert(extractedInfo.queueFamilyProps.present.index != QueueFamilyProps::InvalidIndex); - remainingQueueCounts[extractedInfo.queueFamilyProps.present.index] -= extractedInfo.queueFamilyProps.present.dedicatedQueueCount; - } - - if(!headlessCompute) - assert(extractedInfo.queueFamilyProps.graphics.supportsTransfer && "This shouldn't happen"); - assert(extractedInfo.queueFamilyProps.compute.supportsTransfer && "This shouldn't happen"); - } - - extractedInfo.isSwapChainSupported = gpu->isSwapchainSupported(); - - // Check if the surface is adequate - if(surface) - { - uint32_t surfaceFormatCount; - surface->getAvailableFormatsForPhysicalDevice(gpu, surfaceFormatCount, nullptr); - extractedInfo.availableSurfaceFormats = std::vector(surfaceFormatCount); - surface->getAvailableFormatsForPhysicalDevice(gpu, surfaceFormatCount, extractedInfo.availableSurfaceFormats.data()); - - extractedInfo.availablePresentModes = surface->getAvailablePresentModesForPhysicalDevice(gpu); - - // TODO: @achal OpenGL shouldn't fail this - extractedInfo.surfaceCapabilities = {}; - if (surface->getSurfaceCapabilitiesForPhysicalDevice(gpu, extractedInfo.surfaceCapabilities)) - extractedInfo.hasSurfaceCapabilities = true; - } - } - - return extractedInfos; - } + const bool headlessCompute = false); // TODO: also implement a function:findBestGPU // Returns an index into gpus info vector - static uint32_t findSuitableGPU(const std::vector& extractedInfos, const bool headlessCompute) + static uint32_t findSuitableGPU(const std::vector& extractedInfos, const bool headlessCompute); + + template + struct SFeatureRequest { - uint32_t ret = ~0u; - for(uint32_t i = 0; i < extractedInfos.size(); ++i) - { - bool isGPUSuitable = false; - const auto& extractedInfo = extractedInfos[i]; + uint32_t count = 0u; + FeatureType* features = nullptr; + }; - if(!headlessCompute) - { - if ((extractedInfo.queueFamilyProps.graphics.index != QueueFamilyProps::InvalidIndex) && - (extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex) && - (extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex) && - (extractedInfo.queueFamilyProps.present.index != QueueFamilyProps::InvalidIndex)) - isGPUSuitable = true; - - if(extractedInfo.isSwapChainSupported == false) - isGPUSuitable = false; + struct InitParams + { + std::string_view appName; + nbl::video::E_API_TYPE apiType = nbl::video::EAT_VULKAN; + + uint32_t framesInFlight = 5u; + uint32_t windowWidth = 800u; + uint32_t windowHeight = 600u; + uint32_t swapchainImageCount = 3u; - if(extractedInfo.hasSurfaceCapabilities == false) - isGPUSuitable = false; - } - else - { - if ((extractedInfo.queueFamilyProps.compute.index != QueueFamilyProps::InvalidIndex) && - (extractedInfo.queueFamilyProps.transfer.index != QueueFamilyProps::InvalidIndex)) - isGPUSuitable = true; - } + SFeatureRequest requiredInstanceFeatures = {}; + SFeatureRequest optionalInstanceFeatures = {}; + SFeatureRequest requiredDeviceFeatures = {}; + SFeatureRequest optionalDeviceFeatures = {}; + + nbl::asset::IImage::E_USAGE_FLAGS swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS::EUF_COLOR_ATTACHMENT_BIT; - if(isGPUSuitable) - { - // find the first suitable GPU - ret = i; - break; - } - } + constexpr static inline std::array defaultAcceptableSurfaceFormats = { nbl::asset::EF_R8G8B8A8_SRGB, nbl::asset::EF_R8G8B8A8_UNORM, nbl::asset::EF_B8G8R8A8_SRGB, nbl::asset::EF_B8G8R8A8_UNORM }; + constexpr static inline std::array defaultAcceptableColorPrimaries = { nbl::asset::ECP_SRGB }; + constexpr static inline std::array defaultAcceptableEotfs = { nbl::asset::EOTF_sRGB }; + constexpr static inline std::array defaultAcceptablePresentModes = { nbl::video::ISurface::EPM_FIFO_RELAXED }; + constexpr static inline std::array defaultAcceptableSurfaceTransforms = { nbl::video::ISurface::EST_IDENTITY_BIT, nbl::video::ISurface::EST_HORIZONTAL_MIRROR_ROTATE_180_BIT }; - if(ret == ~0u) - { - //_NBL_DEBUG_BREAK_IF(true); - ret = 0; - } + const nbl::asset::E_FORMAT* acceptableSurfaceFormats = &defaultAcceptableSurfaceFormats[0]; + uint32_t acceptableSurfaceFormatCount = defaultAcceptableSurfaceFormats.size(); + const nbl::asset::E_COLOR_PRIMARIES* acceptableColorPrimaries = &defaultAcceptableColorPrimaries[0]; + uint32_t acceptableColorPrimaryCount = defaultAcceptableColorPrimaries.size(); + const nbl::asset::ELECTRO_OPTICAL_TRANSFER_FUNCTION* acceptableEotfs = &defaultAcceptableEotfs[0]; + uint32_t acceptableEotfCount = defaultAcceptableEotfs.size(); + const nbl::video::ISurface::E_PRESENT_MODE* acceptablePresentModes = &defaultAcceptablePresentModes[0]; + uint32_t acceptablePresentModeCount = defaultAcceptablePresentModes.size(); + const nbl::video::ISurface::E_SURFACE_TRANSFORM_FLAGS* acceptableSurfaceTransforms = &defaultAcceptableSurfaceTransforms[0]; + uint32_t acceptableSurfaceTransformCount = defaultAcceptableSurfaceTransforms.size(); - return ret; - } + nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN; - template - struct SFeatureRequest - { - uint32_t count = 0u; - FeatureType* features = nullptr; + nbl::core::smart_refctd_ptr window = nullptr; + nbl::core::smart_refctd_ptr windowManager = nullptr; + nbl::core::smart_refctd_ptr windowCb = nullptr; + nbl::core::bitflag logLevel = + nbl::core::bitflag(nbl::system::ILogger::ELL_DEBUG) | nbl::system::ILogger::ELL_PERFORMANCE | nbl::system::ILogger::ELL_WARNING | nbl::system::ILogger::ELL_ERROR | nbl::system::ILogger::ELL_INFO; + + constexpr bool isHeadlessCompute() + { + return swapchainImageUsage == nbl::asset::IImage::E_USAGE_FLAGS(0); + } }; struct InitOutput @@ -822,8 +442,6 @@ class CommonAPI static constexpr uint32_t MaxQueuesCount = EQT_COUNT; static constexpr uint32_t MaxSwapChainImageCount = 4; - nbl::core::smart_refctd_ptr window; - nbl::core::smart_refctd_ptr windowCb; nbl::core::smart_refctd_ptr apiConnection; nbl::core::smart_refctd_ptr surface; nbl::core::smart_refctd_ptr utilities; @@ -831,14 +449,14 @@ class CommonAPI nbl::video::IPhysicalDevice* physicalDevice; std::array queues = { nullptr, nullptr, nullptr, nullptr }; std::array, MaxFramesInFlight>, MaxQueuesCount> commandPools; // TODO: Multibuffer and reset the commandpools - nbl::core::smart_refctd_ptr swapchain; - nbl::core::smart_refctd_ptr renderpass; - std::array, MaxSwapChainImageCount> fbo; + nbl::core::smart_refctd_ptr renderToSwapchainRenderpass; nbl::core::smart_refctd_ptr system; nbl::core::smart_refctd_ptr assetManager; nbl::video::IGPUObjectFromAssetConverter::SParams cpu2gpuParams; - nbl::core::smart_refctd_ptr logger; nbl::core::smart_refctd_ptr inputSystem; + nbl::video::ISwapchain::SCreationParams swapchainCreationParams; + nbl::core::smart_refctd_ptr logger; + nbl::core::smart_refctd_ptr windowManager; }; template @@ -867,463 +485,60 @@ class CommonAPI #ifdef _NBL_PLATFORM_ANDROID_ static void recreateSurface(nbl::ui::CGraphicalApplicationAndroid* framework) { - using namespace nbl; - android_app* app = framework->getApp(); - auto apiConnection = framework->getAPIConnection(); - auto window = framework->getWindow(); - auto logicalDevice = framework->getLogicalDevice(); - auto surface = nbl::video::CSurfaceGLAndroid::create(nbl::core::smart_refctd_ptr((nbl::video::COpenGLESConnection*)apiConnection), nbl::core::smart_refctd_ptr(static_cast(window))); - auto renderpass = framework->getRenderpass(); - nbl::asset::E_FORMAT depthFormat = framework->getDepthFormat(); - framework->setSurface(surface); - uint32_t width = ANativeWindow_getWidth(app->window); - uint32_t height = ANativeWindow_getHeight(app->window); - uint32_t scImageCount = framework->getSwapchainImageCount(); - nbl::video::ISurface::SFormat requestedFormat; - - // Temporary to make previous examples work - requestedFormat.format = nbl::asset::EF_R8G8B8A8_SRGB; - requestedFormat.colorSpace.eotf = nbl::asset::EOTF_sRGB; - requestedFormat.colorSpace.primary = nbl::asset::ECP_SRGB; - - auto gpus = apiConnection->getPhysicalDevices(); - assert(!gpus.empty()); - auto extractedInfos = extractGPUInfos(gpus, surface); - auto suitableGPUIndex = findSuitableGPU(extractedInfos, true); - auto gpu = gpus.begin()[suitableGPUIndex]; - const auto& gpuInfo = extractedInfos[suitableGPUIndex]; - - auto swapchain = createSwapchain(nbl::video::EAT_OPENGL_ES, - gpuInfo, - scImageCount, - width, - height, - nbl::core::smart_refctd_ptr(logicalDevice), - surface, - nbl::asset::IImage::E_USAGE_FLAGS::EUF_NONE, - nbl::video::ISurface::EPM_FIFO_RELAXED, - requestedFormat - ); - auto fbo = [&]() - { - auto fbos = createFBOWithSwapchainImages(scImageCount, - width, - height, - nbl::core::smart_refctd_ptr(logicalDevice), - swapchain, - nbl::core::smart_refctd_ptr(renderpass), - depthFormat - ); - - std::vector> data; - for(auto it : fbos) - data.push_back(it); - - return data; - }(); - - framework->setSwapchain(std::move(swapchain)); - framework->setFBOs(fbo); + // Will handle android properly later + _NBL_TODO(); } #endif - + template - static void Init( - InitOutput& result, - nbl::video::E_API_TYPE api_type, - const std::string_view app_name, - const SFeatureRequest& requiredInstanceFeatures, - const SFeatureRequest& optionalInstanceFeatures, - const SFeatureRequest& requiredDeviceFeatures, - const SFeatureRequest& optionalDeviceFeatures, - uint32_t framesInFlight = 0u, - uint32_t window_width = 0u, - uint32_t window_height = 0u, - uint32_t sc_image_count = 0u, - nbl::asset::IImage::E_USAGE_FLAGS swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS::EUF_NONE, - nbl::video::ISurface::SFormat surfaceFormat = nbl::video::ISurface::SFormat(nbl::asset::EF_UNKNOWN, nbl::asset::ECP_COUNT, nbl::asset::EOTF_UNKNOWN), - nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN) + static InitOutput Init(InitParams&& params) { using namespace nbl; using namespace nbl::video; - bool headlessCompute = (swapchainImageUsage == nbl::asset::IImage::E_USAGE_FLAGS::EUF_NONE || sc_image_count <= 0u || window_width <= 0u || window_height <= 0u); + InitOutput result; - auto logLevelMask = nbl::core::bitflag(system::ILogger::ELL_DEBUG) | system::ILogger::ELL_PERFORMANCE | system::ILogger::ELL_WARNING | system::ILogger::ELL_ERROR | system::ILogger::ELL_INFO; + bool headlessCompute = params.isHeadlessCompute(); #ifdef _NBL_PLATFORM_WINDOWS_ result.system = createSystem(); - result.logger = nbl::core::make_smart_refctd_ptr(logLevelMask); // we should let user choose it? +#endif + +#ifdef _NBL_PLATFORM_WINDOWS_ + result.logger = nbl::core::make_smart_refctd_ptr(params.logLevel); #elif defined(_NBL_PLATFORM_ANDROID_) - result.logger = nbl::core::make_smart_refctd_ptr(logLevelMask); // we should let user choose it? + result.logger = nbl::core::make_smart_refctd_ptr(params.logLevel); #endif + result.inputSystem = nbl::core::make_smart_refctd_ptr(system::logger_opt_smart_ptr(nbl::core::smart_refctd_ptr(result.logger))); result.assetManager = nbl::core::make_smart_refctd_ptr(nbl::core::smart_refctd_ptr(result.system)); // we should let user choose it? - - if(!headlessCompute) - { -#ifndef _NBL_PLATFORM_ANDROID_ - auto windowManager = nbl::core::make_smart_refctd_ptr(); // should we store it in result? - result.windowCb = nbl::core::make_smart_refctd_ptr(nbl::core::smart_refctd_ptr(result.inputSystem), system::logger_opt_smart_ptr(nbl::core::smart_refctd_ptr(result.logger))); - - nbl::ui::IWindow::SCreationParams windowsCreationParams; - windowsCreationParams.width = window_width; - windowsCreationParams.height = window_height; - windowsCreationParams.x = 64u; - windowsCreationParams.y = 64u; - windowsCreationParams.system = nbl::core::smart_refctd_ptr(result.system); - windowsCreationParams.flags = nbl::ui::IWindow::ECF_NONE; - windowsCreationParams.windowCaption = app_name.data(); - windowsCreationParams.callback = result.windowCb; - - result.window = windowManager->createWindow(std::move(windowsCreationParams)); - result.windowCb->setInputSystem(nbl::core::smart_refctd_ptr(result.inputSystem)); -#else - result.windowCb = nbl::core::smart_refctd_ptr((CommonAPIEventCallback*)result.window->getEventCallback()); - result.windowCb->setInputSystem(nbl::core::smart_refctd_ptr(result.inputSystem)); -#endif - } - if constexpr (gpuInit) + if (!headlessCompute) { - if (api_type == EAT_VULKAN) + if (!params.window) { - auto _apiConnection = nbl::video::CVulkanConnection::create( - nbl::core::smart_refctd_ptr(result.system), - 0, - app_name.data(), - requiredInstanceFeatures.count, - requiredInstanceFeatures.features, - optionalInstanceFeatures.count, - optionalInstanceFeatures.features, - nbl::core::smart_refctd_ptr(result.logger), - true); - - if(!headlessCompute) - { - #ifdef _NBL_PLATFORM_WINDOWS_ - result.surface = nbl::video::CSurfaceVulkanWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #elif defined(_NBL_PLATFORM_ANDROID_) - ////result.surface = nbl::video::CSurfaceVulkanAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #endif - } - result.apiConnection = _apiConnection; - } - else if (api_type == EAT_OPENGL) - { - auto _apiConnection = nbl::video::COpenGLConnection::create(nbl::core::smart_refctd_ptr(result.system), 0, app_name.data(), nbl::video::COpenGLDebugCallback(nbl::core::smart_refctd_ptr(result.logger))); - - if(!headlessCompute) - { - #ifdef _NBL_PLATFORM_WINDOWS_ - result.surface = nbl::video::CSurfaceGLWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #elif defined(_NBL_PLATFORM_ANDROID_) - result.surface = nbl::video::CSurfaceGLAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #endif - } - - result.apiConnection = _apiConnection; - } - else if (api_type == EAT_OPENGL_ES) - { - auto _apiConnection = nbl::video::COpenGLESConnection::create(nbl::core::smart_refctd_ptr(result.system), 0, app_name.data(), nbl::video::COpenGLDebugCallback(nbl::core::smart_refctd_ptr(result.logger))); - - if(!headlessCompute) - { - #ifdef _NBL_PLATFORM_WINDOWS_ - result.surface = nbl::video::CSurfaceGLWin32::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #elif defined(_NBL_PLATFORM_ANDROID_) - result.surface = nbl::video::CSurfaceGLAndroid::create(nbl::core::smart_refctd_ptr(_apiConnection), nbl::core::smart_refctd_ptr(static_cast(result.window.get()))); - #endif - } - - result.apiConnection = _apiConnection; - } - else - { - _NBL_TODO(); - } - - auto gpus = result.apiConnection->getPhysicalDevices(); - assert(!gpus.empty()); - auto extractedInfos = extractGPUInfos(gpus, result.surface, headlessCompute); - auto suitableGPUIndex = findSuitableGPU(extractedInfos, headlessCompute); - auto gpu = gpus.begin()[suitableGPUIndex]; - const auto& gpuInfo = extractedInfos[suitableGPUIndex]; - - // Fill QueueCreationParams - constexpr uint32_t MaxQueuesInFamily = 32; - float queuePriorities[MaxQueuesInFamily]; - std::fill(queuePriorities, queuePriorities + MaxQueuesInFamily, IGPUQueue::DEFAULT_QUEUE_PRIORITY); - - constexpr uint32_t MaxQueueFamilyCount = 4; - nbl::video::ILogicalDevice::SQueueCreationParams qcp[MaxQueueFamilyCount] = {}; - - uint32_t actualQueueParamsCount = 0u; - - uint32_t queuesIndexInFamily[InitOutput::EQT_COUNT]; - uint32_t presentQueueIndexInFamily = 0u; - - // Graphics Queue - if(!headlessCompute) - { - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.graphics.dedicatedQueueCount; - assert(dedicatedQueuesInFamily >= 1u); - - qcp[0].familyIndex = gpuInfo.queueFamilyProps.graphics.index; - qcp[0].count = dedicatedQueuesInFamily; - qcp[0].flags = static_cast(0); - qcp[0].priorities = queuePriorities; - queuesIndexInFamily[InitOutput::EQT_GRAPHICS] = 0u; - actualQueueParamsCount++; - } - - // Compute Queue - bool foundComputeInOtherFamily = false; - for(uint32_t i = 0; i < actualQueueParamsCount; ++i) - { - auto& otherQcp = qcp[i]; - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.compute.dedicatedQueueCount; - if(otherQcp.familyIndex == gpuInfo.queueFamilyProps.compute.index) - { - if(dedicatedQueuesInFamily >= 1) - { - queuesIndexInFamily[InitOutput::EQT_COMPUTE] = otherQcp.count + 0u; - } - else - { - queuesIndexInFamily[InitOutput::EQT_COMPUTE] = 0u; - } - otherQcp.count += dedicatedQueuesInFamily; - foundComputeInOtherFamily = true; - break; // If works correctly no need to check other family indices as they are unique - } - } - if(!foundComputeInOtherFamily) - { - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.compute.dedicatedQueueCount; - assert(dedicatedQueuesInFamily == 1u); - - queuesIndexInFamily[InitOutput::EQT_COMPUTE] = 0u; - - auto & computeQcp = qcp[actualQueueParamsCount]; - computeQcp.familyIndex = gpuInfo.queueFamilyProps.compute.index; - computeQcp.count = dedicatedQueuesInFamily; - computeQcp.flags = static_cast(0); - computeQcp.priorities = queuePriorities; - actualQueueParamsCount++; - } - - // Transfer Queue - bool foundTransferInOtherFamily = false; - for(uint32_t i = 0; i < actualQueueParamsCount; ++i) - { - auto& otherQcp = qcp[i]; - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.transfer.dedicatedQueueCount; - if(otherQcp.familyIndex == gpuInfo.queueFamilyProps.transfer.index) - { - if(dedicatedQueuesInFamily >= 2u) - { - queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = otherQcp.count + 0u; - queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = otherQcp.count + 1u; - } - else if(dedicatedQueuesInFamily >= 1u) - { - queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = otherQcp.count + 0u; - queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = otherQcp.count + 0u; - } - else if(dedicatedQueuesInFamily == 0u) - { - queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; - queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 0u; - } - otherQcp.count += dedicatedQueuesInFamily; - foundTransferInOtherFamily = true; - break; // If works correctly no need to check other family indices as they are unique - } - } - if(!foundTransferInOtherFamily) - { - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.transfer.dedicatedQueueCount; - assert(dedicatedQueuesInFamily >= 1u); - - if(dedicatedQueuesInFamily >= 2u) - { - queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; - queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 1u; - } - else if(dedicatedQueuesInFamily >= 1u) - { - queuesIndexInFamily[InitOutput::EQT_TRANSFER_UP] = 0u; - queuesIndexInFamily[InitOutput::EQT_TRANSFER_DOWN] = 0u; - } - else - { - assert(false); - } - - auto & transferQcp = qcp[actualQueueParamsCount]; - transferQcp.familyIndex = gpuInfo.queueFamilyProps.transfer.index; - transferQcp.count = dedicatedQueuesInFamily; - transferQcp.flags = static_cast(0); - transferQcp.priorities = queuePriorities; - actualQueueParamsCount++; - } - - // Present Queue - if(!headlessCompute) - { - bool foundPresentInOtherFamily = false; - for(uint32_t i = 0; i < actualQueueParamsCount; ++i) - { - auto& otherQcp = qcp[i]; - if(otherQcp.familyIndex == gpuInfo.queueFamilyProps.present.index) - { - if(otherQcp.familyIndex == gpuInfo.queueFamilyProps.graphics.index) - { - presentQueueIndexInFamily = 0u; - } - else - { - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.present.dedicatedQueueCount; - - if(dedicatedQueuesInFamily >= 1u) - { - presentQueueIndexInFamily = otherQcp.count + 0u; - } - else if(dedicatedQueuesInFamily == 0u) - { - presentQueueIndexInFamily = 0u; - } - otherQcp.count += dedicatedQueuesInFamily; - } - foundPresentInOtherFamily = true; - break; // If works correctly no need to check other family indices as they are unique - } - } - if(!foundPresentInOtherFamily) - { - uint32_t dedicatedQueuesInFamily = gpuInfo.queueFamilyProps.present.dedicatedQueueCount; - assert(dedicatedQueuesInFamily == 1u); - presentQueueIndexInFamily = 0u; - - auto & presentQcp = qcp[actualQueueParamsCount]; - presentQcp.familyIndex = gpuInfo.queueFamilyProps.present.index; - presentQcp.count = dedicatedQueuesInFamily; - presentQcp.flags = static_cast(0); - presentQcp.priorities = queuePriorities; - actualQueueParamsCount++; - } - } - - nbl::video::ILogicalDevice::SCreationParams dev_params; - dev_params.queueParamsCount = actualQueueParamsCount; - dev_params.queueParams = qcp; - dev_params.requiredFeatureCount = requiredDeviceFeatures.count; - dev_params.requiredFeatures = requiredDeviceFeatures.features; - dev_params.optionalFeatureCount = optionalDeviceFeatures.count; - dev_params.optionalFeatures = optionalDeviceFeatures.features; - result.logicalDevice = gpu->createLogicalDevice(dev_params); - - result.utilities = nbl::core::make_smart_refctd_ptr(nbl::core::smart_refctd_ptr(result.logicalDevice)); - - if(!headlessCompute) - result.queues[InitOutput::EQT_GRAPHICS] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, queuesIndexInFamily[InitOutput::EQT_GRAPHICS]); - result.queues[InitOutput::EQT_COMPUTE] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); - - // TEMP_FIX - #ifdef EXAMPLES_CAN_HANDLE_TRANSFER_WITHOUT_GRAPHICS - result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.transfer.index, queuesIndexInFamily[EQT_TRANSFER_UP]); - result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.transfer.index, queuesIndexInFamily[EQT_TRANSFER_DOWN]); - #else - if(!headlessCompute) - { - result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, 0u); - result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.graphics.index, 0u); - } - else - { - result.queues[InitOutput::EQT_TRANSFER_UP] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); - result.queues[InitOutput::EQT_TRANSFER_DOWN] = result.logicalDevice->getQueue(gpuInfo.queueFamilyProps.compute.index, queuesIndexInFamily[InitOutput::EQT_COMPUTE]); - } - #endif - if(!headlessCompute) - { - nbl::video::ISurface::SFormat requestedFormat = surfaceFormat; - if(api_type == EAT_VULKAN) - { - if (requestedFormat.format == nbl::asset::EF_UNKNOWN || requestedFormat.format == asset::EF_R8G8B8A8_SRGB) - { - requestedFormat.format = nbl::asset::EF_B8G8R8A8_SRGB; - requestedFormat.colorSpace.eotf = nbl::asset::EOTF_sRGB; - requestedFormat.colorSpace.primary = nbl::asset::ECP_SRGB; - } - } - else - { - if (requestedFormat.format == nbl::asset::EF_UNKNOWN) - { - requestedFormat.format = nbl::asset::EF_R8G8B8A8_SRGB; - requestedFormat.colorSpace.eotf = nbl::asset::EOTF_sRGB; - requestedFormat.colorSpace.primary = nbl::asset::ECP_SRGB; - } - } - result.swapchain = createSwapchain(api_type, gpuInfo, sc_image_count, window_width, window_height, result.logicalDevice, result.surface, swapchainImageUsage, nbl::video::ISurface::EPM_FIFO_RELAXED, requestedFormat); - assert(result.swapchain); - - nbl::asset::E_FORMAT swapChainFormat = result.swapchain->getCreationParameters().surfaceFormat.format; - result.renderpass = createRenderpass(result.logicalDevice, swapChainFormat, depthFormat); + nbl::core::smart_refctd_ptr windowCallback = nbl::core::make_smart_refctd_ptr(nbl::core::smart_refctd_ptr(result.inputSystem), system::logger_opt_smart_ptr(nbl::core::smart_refctd_ptr(result.logger))); + result.windowManager = nbl::core::make_smart_refctd_ptr(); // on the Android path - result.fbo = createFBOWithSwapchainImages(result.swapchain->getImageCount(), window_width, window_height, result.logicalDevice, result.swapchain, result.renderpass, depthFormat); - } + nbl::ui::IWindow::SCreationParams windowsCreationParams; + windowsCreationParams.width = params.windowWidth; + windowsCreationParams.height = params.windowHeight; + windowsCreationParams.x = 64u; + windowsCreationParams.y = 64u; + windowsCreationParams.system = nbl::core::smart_refctd_ptr(result.system); + windowsCreationParams.flags = nbl::ui::IWindow::ECF_RESIZABLE; + windowsCreationParams.windowCaption = params.appName.data(); + windowsCreationParams.callback = windowCallback; - uint32_t commandPoolsToCreate = core::max(framesInFlight, 1u); - for(uint32_t i = 0; i < InitOutput::EQT_COUNT; ++i) - { - const IGPUQueue* queue = result.queues[i]; - if(queue != nullptr) - { - for (size_t j = 0; j < commandPoolsToCreate; j++) - { - result.commandPools[i][j] = result.logicalDevice->createCommandPool(queue->getFamilyIndex(), IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); - assert(result.commandPools[i][j]); - } - } + params.window = result.windowManager->createWindow(std::move(windowsCreationParams)); } + params.windowCb = nbl::core::smart_refctd_ptr((CommonAPIEventCallback*) params.window->getEventCallback()); + params.windowCb->setInputSystem(nbl::core::smart_refctd_ptr(result.inputSystem)); + } - result.physicalDevice = gpu; - - uint32_t mainQueueFamilyIndex = (headlessCompute) ? gpuInfo.queueFamilyProps.compute.index : gpuInfo.queueFamilyProps.graphics.index; - result.cpu2gpuParams.assetManager = result.assetManager.get(); - result.cpu2gpuParams.device = result.logicalDevice.get(); - result.cpu2gpuParams.finalQueueFamIx = mainQueueFamilyIndex; - result.cpu2gpuParams.limits = result.physicalDevice->getLimits(); - result.cpu2gpuParams.pipelineCache = nullptr; - result.cpu2gpuParams.sharingMode = nbl::asset::ESM_EXCLUSIVE; - result.cpu2gpuParams.utilities = result.utilities.get(); - - result.cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_TRANSFER].queue = result.queues[InitOutput::EQT_TRANSFER_UP]; - result.cpu2gpuParams.perQueue[nbl::video::IGPUObjectFromAssetConverter::EQU_COMPUTE].queue = result.queues[InitOutput::EQT_COMPUTE]; - - const uint32_t transferUpQueueFamIndex = result.queues[InitOutput::EQT_TRANSFER_UP]->getFamilyIndex(); - const uint32_t computeQueueFamIndex = result.queues[InitOutput::EQT_COMPUTE]->getFamilyIndex(); - - auto pool_transfer = result.logicalDevice->createCommandPool(transferUpQueueFamIndex, IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); - nbl::core::smart_refctd_ptr pool_compute; - if(transferUpQueueFamIndex == computeQueueFamIndex) - pool_compute = pool_transfer; - else - pool_compute = result.logicalDevice->createCommandPool(result.queues[InitOutput::EQT_COMPUTE]->getFamilyIndex(), IGPUCommandPool::ECF_RESET_COMMAND_BUFFER_BIT); - - nbl::core::smart_refctd_ptr transferCmdBuffer; - nbl::core::smart_refctd_ptr computeCmdBuffer; - - result.logicalDevice->createCommandBuffers(pool_transfer.get(), IGPUCommandBuffer::EL_PRIMARY, 1u, &transferCmdBuffer); - result.logicalDevice->createCommandBuffers(pool_compute.get(), IGPUCommandBuffer::EL_PRIMARY, 1u, &computeCmdBuffer); - - result.cpu2gpuParams.perQueue[IGPUObjectFromAssetConverter::EQU_TRANSFER].cmdbuf = transferCmdBuffer; - result.cpu2gpuParams.perQueue[IGPUObjectFromAssetConverter::EQU_COMPUTE].cmdbuf = computeCmdBuffer; - + if constexpr (gpuInit) + { + performGpuInit(params, result); } else { @@ -1331,387 +546,91 @@ class CommonAPI result.cpu2gpuParams.finalQueueFamIx = 0u; result.cpu2gpuParams.limits = {}; result.cpu2gpuParams.pipelineCache = nullptr; - result.cpu2gpuParams.sharingMode = nbl::asset::ESM_EXCLUSIVE; result.cpu2gpuParams.utilities = nullptr; } + + return result; } - // Usefull Abstraction for initializing with no extension - template - static void InitWithNoExt( - InitOutput& result, - nbl::video::E_API_TYPE api_type, - const std::string_view app_name, - uint32_t framesInFlight = 0u) + static nbl::video::ISwapchain::SCreationParams computeSwapchainCreationParams( + const GPUInfo& gpuInfo, uint32_t& imageCount, + const nbl::core::smart_refctd_ptr& device, + const nbl::core::smart_refctd_ptr& surface, + nbl::asset::IImage::E_USAGE_FLAGS imageUsage, + // Acceptable settings, ordered by preference. + const nbl::asset::E_FORMAT* acceptableSurfaceFormats, uint32_t acceptableSurfaceFormatCount, + const nbl::asset::E_COLOR_PRIMARIES* acceptableColorPrimaries, uint32_t acceptableColorPrimaryCount, + const nbl::asset::ELECTRO_OPTICAL_TRANSFER_FUNCTION* acceptableEotfs, uint32_t acceptableEotfCount, + const nbl::video::ISurface::E_PRESENT_MODE* acceptablePresentModes, uint32_t acceptablePresentModeCount, + const nbl::video::ISurface::E_SURFACE_TRANSFORM_FLAGS* acceptableSurfaceTransforms, uint32_t acceptableSurfaceTransformsCount + ); + + + class IRetiredSwapchainResources: public nbl::video::ICleanup { - SFeatureRequest requiredInstanceFeatures = {}; - SFeatureRequest optionalInstanceFeatures = {}; - SFeatureRequest requiredDeviceFeatures = {}; - SFeatureRequest optionalDeviceFeatures = {}; + public: + // nbl::core::smart_refctd_ptr oldSwapchain = nullptr; // this gets dropped along with the images + uint64_t retiredFrameId = 0; + }; - Init( - result, - api_type, - app_name, - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures); - } + static void dropRetiredSwapchainResources(nbl::core::deque& qRetiredSwapchainResources, const uint64_t completedFrameId); + static void retireSwapchainResources(nbl::core::deque& qRetiredSwapchainResources, IRetiredSwapchainResources* retired); + + static bool createSwapchain( + const nbl::core::smart_refctd_ptr&& device, + nbl::video::ISwapchain::SCreationParams& params, + uint32_t width, uint32_t height, + // nullptr for initial creation, old swapchain for eventual resizes + nbl::core::smart_refctd_ptr& swapchain + ); - // Usefull Abstraction for most examples that only need to init with default swapchain and surface extension and nothing more. template - static void InitWithDefaultExt( - InitOutput& result, - nbl::video::E_API_TYPE api_type, - const std::string_view app_name, - uint32_t framesInFlight = 0u, - uint32_t window_width = 0u, - uint32_t window_height = 0u, - uint32_t sc_image_count = 0u, - nbl::asset::IImage::E_USAGE_FLAGS swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS::EUF_NONE, - nbl::video::ISurface::SFormat surfaceFormat = nbl::video::ISurface::SFormat(nbl::asset::EF_UNKNOWN, nbl::asset::ECP_COUNT, nbl::asset::EOTF_UNKNOWN), - nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN) + static InitOutput InitWithDefaultExt(InitParams&& params) { - SFeatureRequest requiredInstanceFeatures = {}; - SFeatureRequest optionalInstanceFeatures = {}; - SFeatureRequest requiredDeviceFeatures = {}; - SFeatureRequest optionalDeviceFeatures = {}; - #ifndef _NBL_PLATFORM_ANDROID_ nbl::video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { nbl::video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - requiredInstanceFeatures.count = 1u; - + params.requiredInstanceFeatures.features = requiredFeatures_Instance; + params.requiredInstanceFeatures.count = 1u; nbl::video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = { nbl::video::ILogicalDevice::EF_SWAPCHAIN }; - requiredDeviceFeatures.features = requiredFeatures_Device; - requiredDeviceFeatures.count = 1u; + params.requiredDeviceFeatures.features = requiredFeatures_Device; + params.requiredDeviceFeatures.count = 1u; #endif - - Init( - result, - api_type, - app_name, - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - framesInFlight, window_width, window_height, sc_image_count, - swapchainImageUsage, surfaceFormat, depthFormat); + return CommonAPI::Init(std::move(params)); } - // Usefull Abstraction for Raytracing Examples template - static void InitWithRaytracingExt( - InitOutput& result, - nbl::video::E_API_TYPE api_type, - const std::string_view app_name, - uint32_t framesInFlight = 0u, - uint32_t window_width = 0u, - uint32_t window_height = 0u, - uint32_t sc_image_count = 0u, - nbl::asset::IImage::E_USAGE_FLAGS swapchainImageUsage = nbl::asset::IImage::E_USAGE_FLAGS::EUF_NONE, - nbl::video::ISurface::SFormat surfaceFormat = nbl::video::ISurface::SFormat(nbl::asset::EF_UNKNOWN, nbl::asset::ECP_COUNT, nbl::asset::EOTF_UNKNOWN), - nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN) + static InitOutput InitWithRaytracingExt(InitParams&& params) { - SFeatureRequest requiredInstanceFeatures = {}; - SFeatureRequest optionalInstanceFeatures = {}; - SFeatureRequest requiredDeviceFeatures = {}; - SFeatureRequest optionalDeviceFeatures = {}; - #ifndef _NBL_PLATFORM_ANDROID_ nbl::video::IAPIConnection::E_FEATURE requiredFeatures_Instance[] = { nbl::video::IAPIConnection::EF_SURFACE }; - requiredInstanceFeatures.features = requiredFeatures_Instance; - requiredInstanceFeatures.count = 1u; - - nbl::video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = - { + params.requiredInstanceFeatures.features = requiredFeatures_Instance; + params.requiredInstanceFeatures.count = 1u; + + nbl::video::ILogicalDevice::E_FEATURE requiredFeatures_Device[] = + { nbl::video::ILogicalDevice::EF_SWAPCHAIN, nbl::video::ILogicalDevice::EF_ACCELERATION_STRUCTURE, nbl::video::ILogicalDevice::EF_RAY_QUERY }; - requiredDeviceFeatures.features = requiredFeatures_Device; - requiredDeviceFeatures.count = 3u; + params.requiredDeviceFeatures.features = requiredFeatures_Device; + params.requiredDeviceFeatures.count = 3u; #endif - - Init( - result, - api_type, - app_name, - requiredInstanceFeatures, - optionalInstanceFeatures, - requiredDeviceFeatures, - optionalDeviceFeatures, - framesInFlight, window_width, window_height, sc_image_count, - swapchainImageUsage, surfaceFormat, depthFormat); - } - - static nbl::core::smart_refctd_ptr createSwapchain( - nbl::video::E_API_TYPE api_type, - const GPUInfo& gpuInfo, - uint32_t& imageCount, uint32_t width, uint32_t height, - const nbl::core::smart_refctd_ptr& device, - const nbl::core::smart_refctd_ptr& surface, - nbl::asset::IImage::E_USAGE_FLAGS imageUsage, - nbl::video::ISurface::E_PRESENT_MODE requestedPresentMode = nbl::video::ISurface::EPM_FIFO_RELAXED, - nbl::video::ISurface::SFormat requestedSurfaceFormat = nbl::video::ISurface::SFormat(nbl::asset::EF_B8G8R8A8_SRGB, nbl::asset::ECP_SRGB, nbl::asset::EOTF_sRGB)) - { - using namespace nbl; - - asset::E_SHARING_MODE imageSharingMode; - if (gpuInfo.queueFamilyProps.graphics.index == gpuInfo.queueFamilyProps.present.index) - imageSharingMode = asset::ESM_EXCLUSIVE; - else - imageSharingMode = asset::ESM_CONCURRENT; - - nbl::video::ISurface::SFormat surfaceFormat; - - if(api_type == nbl::video::EAT_VULKAN) - { - // Deduce format features from imageUsage param - nbl::video::IPhysicalDevice::SFormatImageUsage requiredFormatUsages = {}; - if (imageUsage & asset::IImage::EUF_STORAGE_BIT) - requiredFormatUsages.storageImage = 1; - - _NBL_DEBUG_BREAK_IF((device->getPhysicalDevice()->getImageFormatUsagesOptimal(requestedSurfaceFormat.format) & requiredFormatUsages) != requiredFormatUsages); // requested format doesn't support requiredFormatFeatures for TILING_OPTIMAL - - uint32_t found_format_and_colorspace = ~0u; - uint32_t found_format = ~0u; - uint32_t found_colorspace = ~0u; - for(uint32_t i = 0; i < gpuInfo.availableSurfaceFormats.size(); ++i) - { - const auto& supportedFormat = gpuInfo.availableSurfaceFormats[i]; - const bool hasMatchingFormats = requestedSurfaceFormat.format == supportedFormat.format; - const bool hasMatchingColorspace = requestedSurfaceFormat.colorSpace.eotf == supportedFormat.colorSpace.eotf && requestedSurfaceFormat.colorSpace.primary == supportedFormat.colorSpace.primary; - - const auto& supportedFormatUsages = device->getPhysicalDevice()->getImageFormatUsagesOptimal(supportedFormat.format); - const bool supportedFormatSupportsFeatures = ((supportedFormatUsages & requiredFormatUsages) == requiredFormatUsages); - - if(!supportedFormatSupportsFeatures) - continue; - - if(hasMatchingFormats) - { - if(found_format == ~0u) - found_format = i; - if(hasMatchingColorspace) - { - found_format_and_colorspace = i; - break; - } - } - else if (hasMatchingColorspace) - { - // format with matching eotf and colorspace, but with wider bitdepth is an acceptable substitute - uint32_t supportedFormatChannelCount = getFormatChannelCount(supportedFormat.format); - uint32_t requestedFormatChannelCount = getFormatChannelCount(requestedSurfaceFormat.format); - if(supportedFormatChannelCount >= requestedFormatChannelCount) - { - bool channelsMatch = true; - for(uint32_t c = 0; c < requestedFormatChannelCount; ++c) - { - float requestedFormatChannelPrecision = getFormatPrecision(requestedSurfaceFormat.format, c, 0.0f); - float supportedFormatChannelPrecision = getFormatPrecision(supportedFormat.format, c, 0.0f); - if(supportedFormatChannelPrecision < requestedFormatChannelPrecision) - { - channelsMatch = false; - break; - } - } - - if(channelsMatch) - found_colorspace = i; - } - } - } - - if(found_format_and_colorspace != ~0u) - { - surfaceFormat = gpuInfo.availableSurfaceFormats[found_format_and_colorspace]; - } - else if(found_format != ~0u) // fallback - { - _NBL_DEBUG_BREAK_IF(true); // "Fallback: requested 'colorspace' is not supported." - surfaceFormat = gpuInfo.availableSurfaceFormats[found_format]; - } - else if(found_colorspace != ~0u) // fallback - { - _NBL_DEBUG_BREAK_IF(true); // "Fallback: requested 'format' was not supported, but same colorspace and wider bitdepth was chosen." - surfaceFormat = gpuInfo.availableSurfaceFormats[found_colorspace]; - } - else - { - _NBL_DEBUG_BREAK_IF(true); // "Fallback: requested 'format' and 'colorspace' is not supported." - surfaceFormat = gpuInfo.availableSurfaceFormats[0]; - } - - bool presentModeSupported = (gpuInfo.availablePresentModes & requestedPresentMode) != 0; - if(!presentModeSupported) // fallback - { - requestedPresentMode = nbl::video::ISurface::E_PRESENT_MODE::EPM_FIFO; - _NBL_DEBUG_BREAK_IF(true); // "Fallback: requested 'present mode' is not supported." - } - } - else - { - surfaceFormat = requestedSurfaceFormat; - } - - nbl::video::ISwapchain::SCreationParams sc_params = {}; - sc_params.width = width; - sc_params.height = height; - sc_params.arrayLayers = 1u; - sc_params.minImageCount = imageCount; - sc_params.presentMode = requestedPresentMode; - sc_params.imageUsage = imageUsage; - sc_params.surface = surface; - sc_params.imageSharingMode = imageSharingMode; - sc_params.preTransform = gpuInfo.hasSurfaceCapabilities ? gpuInfo.surfaceCapabilities.currentTransform : nbl::video::ISurface::EST_IDENTITY_BIT; - sc_params.compositeAlpha = nbl::video::ISurface::ECA_OPAQUE_BIT; - sc_params.surfaceFormat = surfaceFormat; - - auto swapchain = device->createSwapchain(std::move(sc_params)); - imageCount = swapchain->getImageCount(); - - return swapchain; + return CommonAPI::Init(std::move(params)); } - static nbl::core::smart_refctd_ptr createRenderpass(const nbl::core::smart_refctd_ptr& device, nbl::asset::E_FORMAT colorAttachmentFormat, nbl::asset::E_FORMAT depthFormat) - { - using namespace nbl; + static nbl::core::smart_refctd_ptr createRenderpass(const nbl::core::smart_refctd_ptr& device, nbl::asset::E_FORMAT colorAttachmentFormat, nbl::asset::E_FORMAT baseDepthFormat); - bool useDepth = asset::isDepthOrStencilFormat(depthFormat); - - nbl::video::IGPURenderpass::SCreationParams::SAttachmentDescription attachments[2]; - attachments[0].initialLayout = asset::EIL_UNDEFINED; - attachments[0].finalLayout = asset::EIL_PRESENT_SRC; - attachments[0].format = colorAttachmentFormat; - attachments[0].samples = asset::IImage::ESCF_1_BIT; - attachments[0].loadOp = nbl::video::IGPURenderpass::ELO_CLEAR; - attachments[0].storeOp = nbl::video::IGPURenderpass::ESO_STORE; - - attachments[1].initialLayout = asset::EIL_UNDEFINED; - attachments[1].finalLayout = asset::EIL_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[1].format = depthFormat; - attachments[1].samples = asset::IImage::ESCF_1_BIT; - attachments[1].loadOp = nbl::video::IGPURenderpass::ELO_CLEAR; - attachments[1].storeOp = nbl::video::IGPURenderpass::ESO_STORE; - - nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription::SAttachmentRef colorAttRef; - colorAttRef.attachment = 0u; - colorAttRef.layout = asset::EIL_COLOR_ATTACHMENT_OPTIMAL; - - nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription::SAttachmentRef depthStencilAttRef; - depthStencilAttRef.attachment = 1u; - depthStencilAttRef.layout = asset::EIL_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - nbl::video::IGPURenderpass::SCreationParams::SSubpassDescription sp; - sp.pipelineBindPoint = asset::EPBP_GRAPHICS; - sp.colorAttachmentCount = 1u; - sp.colorAttachments = &colorAttRef; - if(useDepth) { - sp.depthStencilAttachment = &depthStencilAttRef; - } else { - sp.depthStencilAttachment = nullptr; - } - sp.flags = nbl::video::IGPURenderpass::ESDF_NONE; - sp.inputAttachmentCount = 0u; - sp.inputAttachments = nullptr; - sp.preserveAttachmentCount = 0u; - sp.preserveAttachments = nullptr; - sp.resolveAttachments = nullptr; - - nbl::video::IGPURenderpass::SCreationParams rp_params; - rp_params.attachmentCount = (useDepth) ? 2u : 1u; - rp_params.attachments = attachments; - rp_params.dependencies = nullptr; - rp_params.dependencyCount = 0u; - rp_params.subpasses = &sp; - rp_params.subpassCount = 1u; - - return device->createRenderpass(rp_params); - } - - static auto createFBOWithSwapchainImages( + static nbl::core::smart_refctd_dynamic_array> createFBOWithSwapchainImages( size_t imageCount, uint32_t width, uint32_t height, const nbl::core::smart_refctd_ptr& device, nbl::core::smart_refctd_ptr swapchain, - nbl::core::smart_refctd_ptr renderpass, - nbl::asset::E_FORMAT depthFormat = nbl::asset::EF_UNKNOWN)->std::array, InitOutput::MaxSwapChainImageCount> - { - using namespace nbl; - bool useDepth = asset::isDepthOrStencilFormat(depthFormat); - std::array, InitOutput::MaxSwapChainImageCount> fbo; - auto sc_images = swapchain->getImages(); - assert(sc_images.size() == imageCount); - for (uint32_t i = 0u; i < imageCount; ++i) - { - nbl::core::smart_refctd_ptr view[2] = {}; - - auto img = sc_images.begin()[i]; - { - nbl::video::IGPUImageView::SCreationParams view_params; - view_params.format = img->getCreationParameters().format; - view_params.viewType = asset::IImageView::ET_2D; - view_params.subresourceRange.aspectMask = asset::IImage::EAF_COLOR_BIT; - view_params.subresourceRange.baseMipLevel = 0u; - view_params.subresourceRange.levelCount = 1u; - view_params.subresourceRange.baseArrayLayer = 0u; - view_params.subresourceRange.layerCount = 1u; - view_params.image = std::move(img); - - view[0] = device->createImageView(std::move(view_params)); - assert(view[0]); - } - - if(useDepth) { - nbl::video::IGPUImage::SCreationParams imgParams; - imgParams.flags = static_cast(0u); - imgParams.type = asset::IImage::ET_2D; - imgParams.format = depthFormat; - imgParams.extent = {width, height, 1}; - imgParams.usage = asset::IImage::E_USAGE_FLAGS::EUF_DEPTH_STENCIL_ATTACHMENT_BIT; - imgParams.mipLevels = 1u; - imgParams.arrayLayers = 1u; - imgParams.samples = asset::IImage::ESCF_1_BIT; - - auto depthImg = device->createImage(std::move(imgParams)); - auto depthImgMemReqs = depthImg->getMemoryReqs(); - depthImgMemReqs.memoryTypeBits &= device->getPhysicalDevice()->getDeviceLocalMemoryTypeBits(); - auto depthImgMem = device->allocate(depthImgMemReqs, depthImg.get()); - - nbl::video::IGPUImageView::SCreationParams view_params; - view_params.format = depthFormat; - view_params.viewType = asset::IImageView::ET_2D; - view_params.subresourceRange.aspectMask = asset::IImage::EAF_DEPTH_BIT; - view_params.subresourceRange.baseMipLevel = 0u; - view_params.subresourceRange.levelCount = 1u; - view_params.subresourceRange.baseArrayLayer = 0u; - view_params.subresourceRange.layerCount = 1u; - view_params.image = std::move(depthImg); - - view[1] = device->createImageView(std::move(view_params)); - assert(view[1]); - } - - nbl::video::IGPUFramebuffer::SCreationParams fb_params; - fb_params.width = width; - fb_params.height = height; - fb_params.layers = 1u; - fb_params.renderpass = renderpass; - fb_params.flags = static_cast(0); - fb_params.attachmentCount = (useDepth) ? 2u : 1u; - fb_params.attachments = view; - - fbo[i] = device->createFramebuffer(std::move(fb_params)); - assert(fbo[i]); - } - return fbo; - } + nbl::core::smart_refctd_ptr renderpass, + nbl::asset::E_FORMAT baseDepthFormat = nbl::asset::EF_UNKNOWN + ); static constexpr nbl::asset::E_PIPELINE_STAGE_FLAGS DefaultSubmitWaitStage = nbl::asset::EPSF_COLOR_ATTACHMENT_OUTPUT_BIT; - static void Submit(nbl::video::ILogicalDevice* device, - nbl::video::ISwapchain* sc, + static void Submit( + nbl::video::ILogicalDevice* device, nbl::video::IGPUCommandBuffer* cmdbuf, nbl::video::IGPUQueue* queue, nbl::video::IGPUSemaphore* const waitSemaphore, // usually the image acquire semaphore @@ -1745,23 +664,21 @@ class CommonAPI uint32_t imageNum) { using namespace nbl; - nbl::video::IGPUQueue::SPresentInfo present; + nbl::video::ISwapchain::SPresentInfo present; { - present.swapchainCount = 1u; - present.imgIndices = &imageNum; - nbl::video::ISwapchain* swapchain = sc; - present.swapchains = &swapchain; + present.imgIndex = imageNum; present.waitSemaphoreCount = waitSemaphore ? 1u:0u; present.waitSemaphores = &waitSemaphore; - - queue->present(present); + + sc->present(queue, present); } } + static std::pair, nbl::core::smart_refctd_ptr> createEmpty2DTexture( const nbl::core::smart_refctd_ptr& device, uint32_t width, uint32_t height, - nbl::asset::E_FORMAT format = nbl::asset::E_FORMAT::EF_R8G8B8A8_UNORM) + nbl::asset::E_FORMAT format) { nbl::video::IGPUImage::SCreationParams gpu_image_params; gpu_image_params.mipLevels = 1; @@ -1786,13 +703,13 @@ class CommonAPI return std::pair(image, image_view); } - static int getQueueFamilyIndex(const nbl::video::IPhysicalDevice* gpu, uint32_t requiredQueueFlags) + static int getQueueFamilyIndex(const nbl::video::IPhysicalDevice* gpu, nbl::core::bitflag requiredQueueFlags) { auto props = gpu->getQueueFamilyProperties(); int currentIndex = 0; for (const auto& property : props) { - if ((property.queueFlags.value & requiredQueueFlags) == requiredQueueFlags) + if ((property.queueFlags.value & requiredQueueFlags.value) == requiredQueueFlags.value) { return currentIndex; } @@ -1800,9 +717,10 @@ class CommonAPI } return -1; } +protected: + static void performGpuInit(InitParams& params, InitOutput& result); }; - #ifndef _NBL_PLATFORM_ANDROID_ class GraphicalApplication : public nbl::system::IApplicationFramework, public nbl::ui::IGraphicalApplicationFramework { @@ -1818,6 +736,9 @@ class GraphicalApplication : public nbl::system::IApplicationFramework, public n void recreateSurface() override { } + void onResize(uint32_t w, uint32_t h) override + { + } }; #else class GraphicalApplication : public nbl::ui::CGraphicalApplicationAndroid @@ -1871,3 +792,4 @@ CommonAPI::main(argc, argv);\ #endif //***** Application framework macros ****** +#endif