void GraphicsSystem::Initialize() { mVulkanSuccess = vkelInit(); mBaseQuad.mVertex1.mPosition = { -0.5f, -0.5f, 0.0f, 1.0f }; mBaseQuad.mVertex1.mUVCoordinates = { 0.0f, 0.0f }; mBaseQuad.mVertex1.mNormal = { 0.0f, 0.0f, 1.0 }; mBaseQuad.mVertex2.mPosition = { 0.5f, -0.5f, 0.0f, 1.0f }; mBaseQuad.mVertex2.mUVCoordinates = { 1.0f, 0.0f }; mBaseQuad.mVertex2.mNormal = { 0.0f, 0.0f, 1.0 }; mBaseQuad.mVertex3.mPosition = { 0.5f, 0.5f, 0.0f, 1.0f }; mBaseQuad.mVertex3.mUVCoordinates = { 1.0f, 1.0f }; mBaseQuad.mVertex3.mNormal = { 0.0f, 0.0f, 1.0 }; mBaseQuad.mVertex4.mPosition = { -0.5f, 0.5f, 0.0f, 1.0f }; mBaseQuad.mVertex4.mUVCoordinates = { 0.0f, 1.0f }; mBaseQuad.mVertex4.mNormal = { 0.0f, 0.0f, 1.0 }; if (mVulkanSuccess) { auto self = mPlatformSpecificData.Get<VulkanContext>(); vk::ApplicationInfo appInfo; appInfo.setPApplicationName("First Test"); appInfo.setEngineVersion(1); appInfo.setApiVersion(VK_MAKE_VERSION(1, 0, 0)); auto instanceInfo = vk::InstanceCreateInfo() .setPApplicationInfo(&appInfo); auto layers = vk::enumerateInstanceLayerProperties(); vulkan_assert(layers.size(), "Failed to find layers."); bool foundValidator = false; auto validationLayer = "VK_LAYER_LUNARG_standard_validation"; for (auto &layer : layers) { if (StringCompare(layer.layerName, validationLayer) == StringComparison::Equal) { foundValidator = true; } } if (foundValidator) { } const char *enabledLayers[] = { validationLayer }; if (foundValidator) { #if _DEBUG instanceInfo.setEnabledLayerCount(1); instanceInfo.setPpEnabledLayerNames(enabledLayers); #endif } else { printf("Could not find validation layers."); } auto extensions = vk::enumerateInstanceExtensionProperties(); std::array<const char *, 3> requiredExtensions = { "VK_KHR_surface", "VK_KHR_win32_surface", "VK_EXT_debug_report" }; decltype(requiredExtensions)::size_type foundExtensions = 0; for (auto &extension : extensions) { for (auto &requiredExtension : requiredExtensions) { if (std::strcmp(extension.extensionName, requiredExtension) == 0) { ++foundExtensions; requiredExtension = ""; break; } } } requiredExtensions = { "VK_KHR_surface", "VK_KHR_win32_surface", "VK_EXT_debug_report" }; if (requiredExtensions.size() == foundExtensions) { instanceInfo.setEnabledExtensionCount((u32)requiredExtensions.size()); instanceInfo.setPpEnabledExtensionNames(requiredExtensions.data()); auto result = vk::createInstance(&instanceInfo, nullptr, &self->mInstance); checkVulkanResult(result, "Failed to create vulkan instance."); } else { printf("Could not find debug extension"); } vkelInstanceInit(self->mInstance); if (requiredExtensions.size() == foundExtensions) { vk::DebugReportCallbackCreateInfoEXT callbackCreateInfo; callbackCreateInfo.setFlags(vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning); callbackCreateInfo.setPfnCallback(&DebugReportCallback); auto debugReport = self->mInstance.createDebugReportCallbackEXT(callbackCreateInfo); vulkan_assert(static_cast<bool>(debugReport), "Failed to create degub report callback."); } // TODO: Abstract this for multiple windows. auto window = mEngine->mPrimaryWindow; auto windowData = window->mPlatformSpecificData.Get<WindowData>(); vk::Win32SurfaceCreateInfoKHR surfaceCreateInfo; surfaceCreateInfo.setHinstance(windowData->mInstance); surfaceCreateInfo.setHwnd(windowData->mWindowHandle); self->mHeight = window->mHeight; self->mWidth = window->mWidth; self->mSurface = self->mInstance.createWin32SurfaceKHR(surfaceCreateInfo); auto physicalDevices = self->mInstance.enumeratePhysicalDevices(); u32 deviceCount = 0; for (auto &physicalDevice : physicalDevices) { auto properties = physicalDevice.getProperties(); auto queueProperties = physicalDevice.getQueueFamilyProperties(); printf("Device #%d: %s\n", deviceCount, properties.deviceName); u32 queueCount = 0; for (auto &queueProperty : queueProperties) { i32 supportsPresent = physicalDevice.getSurfaceSupportKHR(queueCount, self->mSurface); if (supportsPresent && (queueProperty.queueFlags & vk::QueueFlagBits::eGraphics)) { self->mPhysicalDevice = physicalDevice; self->mPhysicalDeviceProperties = properties; self->mPresentQueueIdx = queueCount; ++queueCount; break; } ++queueCount; ++deviceCount; } // TODO: Maybe grab more than just one physical device? if (self->mPhysicalDevice) { break; } } vulkan_assert(self->mPhysicalDevice, "No physical device detected that can render and present!"); self->mPhysicalMemoryProperties = self->mPhysicalDevice.getMemoryProperties(); // info for accessing one of the devices rendering queues: vk::DeviceQueueCreateInfo queueCreateInfo; queueCreateInfo.setQueueFamilyIndex(self->mPresentQueueIdx); queueCreateInfo.setQueueCount(1); float queuePriorities[] = { 1.0f }; // ask for highest priority for our queue. (range [0,1]) queueCreateInfo.pQueuePriorities = queuePriorities; const char *deviceExtensions[] = { "VK_KHR_swapchain" }; vk::DeviceCreateInfo deviceInfo; deviceInfo.setQueueCreateInfoCount(1); deviceInfo.setPQueueCreateInfos(&queueCreateInfo); deviceInfo.setEnabledLayerCount(1); deviceInfo.setPpEnabledLayerNames(enabledLayers); deviceInfo.setEnabledExtensionCount(1); deviceInfo.setPpEnabledExtensionNames(deviceExtensions); auto features = vk::PhysicalDeviceFeatures().setShaderClipDistance(true); deviceInfo.setPEnabledFeatures(&features); self->mLogicalDevice = self->mPhysicalDevice.createDevice(deviceInfo); vulkan_assert(self->mLogicalDevice, "Failed to create logical device!"); auto formats = self->mPhysicalDevice.getSurfaceFormatsKHR(self->mSurface); // If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has // no preferred format. Otherwise, at least one supported format will be returned. vk::Format colorFormat; if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) { colorFormat = vk::Format::eB8G8R8Unorm; } else { colorFormat = formats[0].format; } vk::ColorSpaceKHR colorSpace; colorSpace = formats[0].colorSpace; vk::SurfaceCapabilitiesKHR surfaceCapabilities = self->mPhysicalDevice.getSurfaceCapabilitiesKHR(self->mSurface); // We are effectively looking for double-buffering: // if surfaceCapabilities.maxImageCount == 0 there is actually no limit on the number of images! // // TODO: Make the amount of buffering configurable. u32 desiredImageCount = 2; if (desiredImageCount < surfaceCapabilities.minImageCount) { desiredImageCount = surfaceCapabilities.minImageCount; } else if ((surfaceCapabilities.maxImageCount != 0) && (desiredImageCount > surfaceCapabilities.maxImageCount)) { desiredImageCount = surfaceCapabilities.maxImageCount; } vk::Extent2D surfaceResolution = surfaceCapabilities.currentExtent; if (surfaceResolution.width == -1) { surfaceResolution.width = self->mWidth; surfaceResolution.height = self->mHeight; } else { self->mWidth = surfaceResolution.width; self->mHeight = surfaceResolution.height; } vk::SurfaceTransformFlagBitsKHR preTransform = surfaceCapabilities.currentTransform; if (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) { preTransform = vk::SurfaceTransformFlagBitsKHR::eIdentity; } auto presentModes = self->mPhysicalDevice.getSurfacePresentModesKHR(self->mSurface); // Always supported. vk::PresentModeKHR presentationMode = vk::PresentModeKHR::eFifo; // TODO: Look into the rest of the vk::PresentModeKHR options. for (auto &presentMode : presentModes) { // This is what we'd prefer. if (presentMode == vk::PresentModeKHR::eMailbox) { presentationMode = vk::PresentModeKHR::eMailbox; break; } // We'll take this if Mailbox isn't available. else if (presentMode == vk::PresentModeKHR::eFifoRelaxed) { presentationMode = vk::PresentModeKHR::eFifoRelaxed; } } vk::SwapchainCreateInfoKHR swapChainCreateInfo; swapChainCreateInfo.setSurface(self->mSurface); swapChainCreateInfo.setMinImageCount(desiredImageCount); swapChainCreateInfo.setImageFormat(colorFormat); swapChainCreateInfo.setImageColorSpace(colorSpace); swapChainCreateInfo.setImageExtent(surfaceResolution); swapChainCreateInfo.setImageArrayLayers(1); swapChainCreateInfo.setImageUsage(vk::ImageUsageFlagBits::eColorAttachment); swapChainCreateInfo.setImageSharingMode(vk::SharingMode::eExclusive); // TODO: Learn how to share queues. swapChainCreateInfo.setPreTransform(preTransform); swapChainCreateInfo.setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque); //TODO: Pretty sure we want to do pre-multiplied. swapChainCreateInfo.setPresentMode(presentationMode); swapChainCreateInfo.setClipped(true); // If we want clipping outside the extents // (remember our device features?) self->mSwapChain = self->mLogicalDevice.createSwapchainKHR(swapChainCreateInfo); vulkan_assert(self->mSwapChain, "Failed to create swapchain."); self->mQueue = self->mLogicalDevice.getQueue(self->mPresentQueueIdx, 0); vk::CommandPoolCreateInfo commandPoolCreateInfo; commandPoolCreateInfo.setFlags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer); commandPoolCreateInfo.setQueueFamilyIndex(self->mPresentQueueIdx); self->mCommandPool = self->mLogicalDevice.createCommandPool(commandPoolCreateInfo); vulkan_assert(self->mCommandPool, "Failed to create command pool."); vk::CommandBufferAllocateInfo commandBufferAllocationInfo; commandBufferAllocationInfo.setCommandPool(self->mCommandPool); commandBufferAllocationInfo.setLevel(vk::CommandBufferLevel::ePrimary); commandBufferAllocationInfo.setCommandBufferCount(1); self->mSetupCommandBuffer = self->mLogicalDevice.allocateCommandBuffers(commandBufferAllocationInfo)[0]; vulkan_assert(self->mSetupCommandBuffer, "Failed to allocate setup command buffer."); self->mPresentImages = self->mLogicalDevice.getSwapchainImagesKHR(self->mSwapChain); commandBufferAllocationInfo.commandBufferCount = static_cast<u32>(self->mPresentImages.size()); self->mDrawCommandBuffers = self->mLogicalDevice.allocateCommandBuffers(commandBufferAllocationInfo); vulkan_assert(self->mDrawCommandBuffers.size(), "Failed to allocate draw command buffer."); vk::ImageViewCreateInfo presentImagesViewCreateInfo; presentImagesViewCreateInfo.setViewType(vk::ImageViewType::e2D); presentImagesViewCreateInfo.setFormat(colorFormat); presentImagesViewCreateInfo.setFlags((vk::ImageViewCreateFlagBits)0); presentImagesViewCreateInfo.setComponents({ vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA }); presentImagesViewCreateInfo.subresourceRange.setAspectMask(vk::ImageAspectFlagBits::eColor); presentImagesViewCreateInfo.subresourceRange.setLevelCount(1); presentImagesViewCreateInfo.subresourceRange.setLayerCount(1); vk::ImageCreateInfo imageCreateInfo; imageCreateInfo.setImageType(vk::ImageType::e2D); imageCreateInfo.setFormat(vk::Format::eD32SfloatS8Uint); imageCreateInfo.setExtent({ self->mWidth, self->mHeight, 1 }); imageCreateInfo.setMipLevels(1); imageCreateInfo.setArrayLayers(1); imageCreateInfo.setSamples(vk::SampleCountFlagBits::e1); imageCreateInfo.setTiling(vk::ImageTiling::eOptimal); imageCreateInfo.setUsage(vk::ImageUsageFlagBits::eDepthStencilAttachment); imageCreateInfo.setSharingMode(vk::SharingMode::eExclusive); // TODO: Change this when you learn more. imageCreateInfo.setInitialLayout(vk::ImageLayout::eUndefined); self->mDepthImage = self->mLogicalDevice.createImage(imageCreateInfo); vulkan_assert(self->mDepthImage, "Failed to create depth image."); auto memoryRequirements = self->mLogicalDevice.getImageMemoryRequirements(self->mDepthImage); auto imageAllocationInfo = vk::MemoryAllocateInfo().setAllocationSize(memoryRequirements.size); // memoryTypeBits is a bitfield where if bit i is set, it means that // the VkMemoryType i of the VkPhysicalDeviceMemoryProperties structure // satisfies the memory requirements: u32 memoryTypeBits = memoryRequirements.memoryTypeBits; vk::MemoryPropertyFlags desiredMemoryFlags = vk::MemoryPropertyFlagBits::eDeviceLocal; for (u32 i = 0; i < 32; ++i) { vk::MemoryType memoryType = self->mPhysicalMemoryProperties.memoryTypes[i]; if (memoryTypeBits & 1) { if ((memoryType.propertyFlags & desiredMemoryFlags) == desiredMemoryFlags) { imageAllocationInfo.memoryTypeIndex = i; break; } } memoryTypeBits = memoryTypeBits >> 1; } auto imageMemory = self->mLogicalDevice.allocateMemory(imageAllocationInfo); self->mLogicalDevice.bindImageMemory(self->mDepthImage, imageMemory, 0); auto beginInfo = vk::CommandBufferBeginInfo().setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); auto submitFence = self->mLogicalDevice.createFence(vk::FenceCreateInfo()); std::vector<bool> transitioned; transitioned.resize(self->mPresentImages.size(), false); // This sets the image layout on the images. u32 doneCount = 0; while (doneCount != self->mPresentImages.size()) { vk::SemaphoreCreateInfo semaphoreCreateInfo; vk::Semaphore presentCompleteSemaphore = self->mLogicalDevice.createSemaphore(semaphoreCreateInfo); u32 nextImageIdx; auto result = self->mLogicalDevice.acquireNextImageKHR(self->mSwapChain, UINT64_MAX, presentCompleteSemaphore, VK_NULL_HANDLE, &nextImageIdx); checkVulkanResult(result, "Could not acquireNextImageKHR."); if (!transitioned.at(nextImageIdx)) { // start recording out image layout change barrier on our setup command buffer: self->mSetupCommandBuffer.begin(&beginInfo); vk::ImageMemoryBarrier layoutTransitionBarrier; layoutTransitionBarrier.setDstAccessMask(vk::AccessFlagBits::eMemoryRead); layoutTransitionBarrier.setOldLayout(vk::ImageLayout::eUndefined); layoutTransitionBarrier.setNewLayout(vk::ImageLayout::ePresentSrcKHR); layoutTransitionBarrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); layoutTransitionBarrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); layoutTransitionBarrier.setImage(self->mPresentImages[nextImageIdx]); vk::ImageSubresourceRange resourceRange = { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 }; layoutTransitionBarrier.setSubresourceRange(resourceRange); vk::ClearColorValue clear; clear.setFloat32( { 0.0f, 0.0f, 0.0f, 1.0f }); self->mSetupCommandBuffer.clearColorImage(self->mPresentImages[nextImageIdx], vk::ImageLayout::eTransferDstOptimal, clear, resourceRange); self->mSetupCommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlags(), nullptr, nullptr, layoutTransitionBarrier); self->mSetupCommandBuffer.end(); vk::PipelineStageFlags waitStageMash[] = { vk::PipelineStageFlagBits::eColorAttachmentOutput }; vk::SubmitInfo submitInfo; submitInfo.setWaitSemaphoreCount(1); submitInfo.setPWaitSemaphores(&presentCompleteSemaphore); submitInfo.setPWaitDstStageMask(waitStageMash); submitInfo.setCommandBufferCount(1); submitInfo.setPCommandBuffers(&self->mSetupCommandBuffer); self->mQueue.submit(submitInfo, submitFence); self->mLogicalDevice.waitForFences(submitFence, true, UINT64_MAX); self->mLogicalDevice.resetFences(submitFence); self->mLogicalDevice.destroySemaphore(presentCompleteSemaphore); // NOTE: Instead of eReleaseResources should it be 0? self->mSetupCommandBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources); transitioned[nextImageIdx] = true; ++doneCount; } // TODO: Fix the issue where we present without writing to the images. auto presentInfo = vk::PresentInfoKHR() .setSwapchainCount(1) .setPSwapchains(&self->mSwapChain) .setPImageIndices(&nextImageIdx); self->mQueue.presentKHR(presentInfo); } self->mPresentImageViews = std::vector<vk::ImageView>(self->mPresentImages.size(), vk::ImageView()); for (uint32_t i = 0; i < self->mPresentImages.size(); ++i) { presentImagesViewCreateInfo.image = self->mPresentImages[i]; self->mPresentImageViews[i] = self->mLogicalDevice.createImageView(presentImagesViewCreateInfo); vulkan_assert(self->mPresentImageViews[i], "Could not create ImageView."); } namespace fs = std::experimental::filesystem; TextureLoader loader(self->mPhysicalDevice, self->mLogicalDevice, self->mQueue, self->mCommandPool); u32 i = 0; for (auto& file : fs::directory_iterator(L"./Textures")) { std::string texturePath = file.path().string(); self->mTextures.emplace_back(loader.loadTexture(texturePath)); } self->mSetupCommandBuffer.begin(beginInfo); vk::ImageMemoryBarrier layoutTransitionBarrier; layoutTransitionBarrier.setDstAccessMask(vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite); layoutTransitionBarrier.setOldLayout(vk::ImageLayout::eUndefined); layoutTransitionBarrier.setNewLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); layoutTransitionBarrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); layoutTransitionBarrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); layoutTransitionBarrier.setImage(self->mDepthImage); auto resourceRange = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1); layoutTransitionBarrier.setSubresourceRange(resourceRange); self->mSetupCommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlags(), nullptr, nullptr, layoutTransitionBarrier); self->mSetupCommandBuffer.end(); vk::PipelineStageFlags waitStageMask[] = { vk::PipelineStageFlagBits::eColorAttachmentOutput }; vk::SubmitInfo submitInfo; submitInfo.setPWaitDstStageMask(waitStageMask); submitInfo.setCommandBufferCount(1); submitInfo.setPCommandBuffers(&self->mSetupCommandBuffer); self->mQueue.submit(submitInfo, submitFence); self->mLogicalDevice.waitForFences(submitFence, true, UINT64_MAX); self->mLogicalDevice.resetFences(submitFence); // NOTE: Instead of eReleaseResources should it be 0? self->mSetupCommandBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources); vk::ImageAspectFlags aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil; vk::ImageViewCreateInfo imageViewCreateInfo; imageViewCreateInfo.setImage(self->mDepthImage); imageViewCreateInfo.setViewType(vk::ImageViewType::e2D); imageViewCreateInfo.setFormat(imageCreateInfo.format); imageViewCreateInfo.setComponents({ vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity , vk::ComponentSwizzle::eIdentity }); imageViewCreateInfo.setSubresourceRange(vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1)); self->mDepthImageView = self->mLogicalDevice.createImageView(imageViewCreateInfo); vulkan_assert(self->mDepthImageView, "Failed to create image view."); std::array<vk::AttachmentDescription, 2> passAttachments = {}; passAttachments[0].format = colorFormat; passAttachments[0].samples = vk::SampleCountFlagBits::e1; passAttachments[0].loadOp = vk::AttachmentLoadOp::eClear; passAttachments[0].storeOp = vk::AttachmentStoreOp::eStore; passAttachments[0].stencilLoadOp = vk::AttachmentLoadOp::eDontCare; passAttachments[0].stencilStoreOp = vk::AttachmentStoreOp::eDontCare; passAttachments[0].initialLayout = vk::ImageLayout::eColorAttachmentOptimal; passAttachments[0].finalLayout = vk::ImageLayout::eColorAttachmentOptimal; //passAttachments[1].format = vk::Format::eD16Unorm; passAttachments[1].format = vk::Format::eD32SfloatS8Uint; passAttachments[1].samples = vk::SampleCountFlagBits::e1; passAttachments[1].loadOp = vk::AttachmentLoadOp::eClear; passAttachments[1].storeOp = vk::AttachmentStoreOp::eDontCare; passAttachments[1].stencilLoadOp = vk::AttachmentLoadOp::eDontCare; passAttachments[1].stencilStoreOp = vk::AttachmentStoreOp::eDontCare; passAttachments[1].initialLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; passAttachments[1].finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; vk::AttachmentReference colorAttachmentReference; colorAttachmentReference.setAttachment(0); // First attachment is the color attachment. colorAttachmentReference.setLayout(vk::ImageLayout::eColorAttachmentOptimal); vk::AttachmentReference depthAttachmentReference; depthAttachmentReference.setAttachment(1); // Second attachment is the depth attachment. depthAttachmentReference.setLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::SubpassDescription subpass; subpass.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics); subpass.setColorAttachmentCount(1); subpass.setPColorAttachments(&colorAttachmentReference); subpass.setPDepthStencilAttachment(&depthAttachmentReference); vk::SubpassDependency subpassDependency; subpassDependency.setSrcStageMask(vk::PipelineStageFlagBits::eTopOfPipe); subpassDependency.setDstStageMask(vk::PipelineStageFlagBits::eTopOfPipe); //subpassDependency.setSrcAccessMask(vk::AccessFlagBits(0)); //subpassDependency.setDstAccessMask(vk::AccessFlagBits(0)); //subpassDependency.setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); //subpassDependency.setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); subpassDependency.setSrcSubpass(0); subpassDependency.setDstSubpass(0); vk::RenderPassCreateInfo renderPassCreateInfo; renderPassCreateInfo.setAttachmentCount(static_cast<u32>(passAttachments.size())); renderPassCreateInfo.setPAttachments(passAttachments.data()); renderPassCreateInfo.setSubpassCount(1); renderPassCreateInfo.setDependencyCount(1); renderPassCreateInfo.setPDependencies(&subpassDependency); renderPassCreateInfo.setPSubpasses(&subpass); self->mRenderPass = self->mLogicalDevice.createRenderPass(renderPassCreateInfo); vulkan_assert(self->mRenderPass, "Failed to create renderpass"); // create our frame buffers: vk::ImageView frameBufferAttachments[2]; frameBufferAttachments[1] = self->mDepthImageView; vk::FramebufferCreateInfo frameBufferCreateInfo = {}; frameBufferCreateInfo.renderPass = self->mRenderPass; frameBufferCreateInfo.attachmentCount = 2; // must be equal to the attachment count on render pass frameBufferCreateInfo.pAttachments = frameBufferAttachments; frameBufferCreateInfo.width = self->mWidth; frameBufferCreateInfo.height = self->mHeight; frameBufferCreateInfo.layers = 1; // create a framebuffer per swap chain imageView: auto imageCount = self->mPresentImages.size(); self->mFrameBuffers = std::vector<vk::Framebuffer>(imageCount, vk::Framebuffer()); for (u32 i = 0; i < imageCount; ++i) { frameBufferAttachments[0] = self->mPresentImageViews[i]; auto result = self->mLogicalDevice.createFramebuffer(&frameBufferCreateInfo, NULL, &self->mFrameBuffers[i]); checkVulkanResult(result, "Failed to create framebuffer."); } // Prepare and initialize a uniform buffer block containing shader uniforms // In Vulkan there are no more single uniforms like in GL // All shader uniforms are passed as uniform buffer blocks // Vertex shader uniform buffer block // Most implementations offer multiple memory types and selecting the // correct one to allocate memory from is important // We also want the buffer to be host coherent so we don't have to flush // after every update. // Note that this may affect performance so you might not want to do this // in a real world application that updates buffers on a regular base self->mUniform = self->CreateBuffer(sizeof(UniformBufferObject), vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); // Store information in the uniform's descriptor self->mUniformBufferInfo.buffer = self->mUniform.mBuffer; self->mUniformBufferInfo.offset = 0; self->mUniformBufferInfo.range = sizeof(UniformBufferObject); self->UpdateUniformBuffers(true); self->SetupDescriptorSetLayout(); Shader vert{ "./Shaders/vert.spv", ShaderType::Vertex, self }; Shader frag{ "./Shaders/frag.spv", ShaderType::Fragment, self }; std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStageCreateInfo; shaderStageCreateInfo[0] = vert.CreateShaderStage(); shaderStageCreateInfo[1] = frag.CreateShaderStage(); ShaderDescriptions descriptions; descriptions.AddBinding<Vertex>(vk::VertexInputRate::eVertex); //glm::vec4 mPosition; descriptions.AddAttribute<glm::vec4>(vk::Format::eR32G32B32A32Sfloat); //glm::vec2 mUVCoordinates; descriptions.AddAttribute<glm::vec2>(vk::Format::eR32G32Sfloat); //glm::vec2 mNormal; descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32Sfloat); /////////////////////////////////////////////////////////// // Instance Attributes /////////////////////////////////////////////////////////// descriptions.AddBinding<Object>(vk::VertexInputRate::eInstance); //glm::vec3 mTranslation descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32Sfloat); //glm::vec3 mScale descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32Sfloat); //glm::vec3 mRotation; descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32Sfloat); //glm::vec3 mColor descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32Sfloat); //u32 mTextureId descriptions.AddAttribute<u32>(vk::Format::eR32Uint); //glm::mat4 mTransform; descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32A32Sfloat); descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32A32Sfloat); descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32A32Sfloat); descriptions.AddAttribute<glm::vec3>(vk::Format::eR32G32B32A32Sfloat); vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo; vertexInputStateCreateInfo.vertexBindingDescriptionCount = static_cast<u32>(descriptions.BindingSize()); vertexInputStateCreateInfo.pVertexBindingDescriptions = descriptions.BindingData(); vertexInputStateCreateInfo.vertexAttributeDescriptionCount = static_cast<u32>(descriptions.AttributeSize()); vertexInputStateCreateInfo.pVertexAttributeDescriptions = descriptions.AttributeData(); // vertex topology config: vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo; inputAssemblyStateCreateInfo.topology = vk::PrimitiveTopology::eTriangleList; vk::Viewport viewport = {}; viewport.width = static_cast<float>(self->mWidth); viewport.height = static_cast<float>(self->mHeight); viewport.maxDepth = 1; vk::Rect2D scissors = {}; scissors.extent.setWidth(self->mWidth).setHeight(self->mHeight); vk::PipelineViewportStateCreateInfo viewportState = {}; viewportState.viewportCount = 1; viewportState.pViewports = &viewport; viewportState.scissorCount = 1; viewportState.pScissors = &scissors; vk::PipelineRasterizationStateCreateInfo rasterizationState; rasterizationState.polygonMode = vk::PolygonMode::eFill; //rasterizationState.cullMode = vk::CullModeFlagBits::eBack; // TODO: Investigate rasterizationState.cullMode = vk::CullModeFlagBits::eNone; rasterizationState.frontFace = vk::FrontFace::eCounterClockwise; //rasterizationState.frontFace = vk::FrontFace::eClockwise; rasterizationState.lineWidth = 1; rasterizationState.depthClampEnable = true; rasterizationState.depthBiasEnable = true; vk::PipelineMultisampleStateCreateInfo multisampleState = {}; multisampleState.rasterizationSamples = vk::SampleCountFlagBits::e1; vk::StencilOpState stencilState = {}; stencilState.failOp = vk::StencilOp::eReplace; stencilState.passOp = vk::StencilOp::eKeep; stencilState.depthFailOp = vk::StencilOp::eReplace; stencilState.compareOp = vk::CompareOp::eLessOrEqual; vk::PipelineDepthStencilStateCreateInfo depthState; depthState.depthTestEnable = true; depthState.depthWriteEnable = true; depthState.depthCompareOp = vk::CompareOp::eLessOrEqual; depthState.setDepthBoundsTestEnable(false); depthState.setStencilTestEnable(false); //depthState.front = noOPStencilState; //depthState.back = noOPStencilState; //depthState.back.compareOp = vk::CompareOp::eAlways; //depthState.front = stencilState; //depthState.back = stencilState; vk::PipelineColorBlendAttachmentState colorBlendAttachmentState; colorBlendAttachmentState.srcColorBlendFactor = vk::BlendFactor::eSrc1Color; colorBlendAttachmentState.dstColorBlendFactor = vk::BlendFactor::eOneMinusDstColor; colorBlendAttachmentState.colorBlendOp = vk::BlendOp::eAdd; colorBlendAttachmentState.srcAlphaBlendFactor = vk::BlendFactor::eZero; colorBlendAttachmentState.dstAlphaBlendFactor = vk::BlendFactor::eZero; colorBlendAttachmentState.alphaBlendOp = vk::BlendOp::eAdd; colorBlendAttachmentState.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA; vk::PipelineColorBlendStateCreateInfo colorBlendState; colorBlendState.logicOpEnable = VK_FALSE; colorBlendState.logicOp = vk::LogicOp::eClear; colorBlendState.attachmentCount = 1; colorBlendState.pAttachments = &colorBlendAttachmentState; colorBlendState.blendConstants[0] = 0.0; colorBlendState.blendConstants[1] = 0.0; colorBlendState.blendConstants[2] = 0.0; colorBlendState.blendConstants[3] = 0.0; vk::DynamicState dynamicState[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo ; dynamicStateCreateInfo.dynamicStateCount = 2; dynamicStateCreateInfo.pDynamicStates = dynamicState; vk::GraphicsPipelineCreateInfo pipelineCreateInfo; pipelineCreateInfo.stageCount = static_cast<u32>(shaderStageCreateInfo.size()); pipelineCreateInfo.pStages = shaderStageCreateInfo.data(); pipelineCreateInfo.pVertexInputState = &vertexInputStateCreateInfo; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo; pipelineCreateInfo.pViewportState = &viewportState; pipelineCreateInfo.pRasterizationState = &rasterizationState; pipelineCreateInfo.pMultisampleState = &multisampleState; pipelineCreateInfo.pDepthStencilState = &depthState; pipelineCreateInfo.pColorBlendState = &colorBlendState; pipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo; pipelineCreateInfo.layout = self->mPipelineLayout; pipelineCreateInfo.renderPass = self->mRenderPass; self->SetupDescriptorPool(); self->SetupDescriptorSet(); self->mPipeline = self->mLogicalDevice.createGraphicsPipelines(VK_NULL_HANDLE, pipelineCreateInfo)[0]; vulkan_assert(self->mPipeline, "Failed to create graphics pipeline."); mQuadIndicies = self->CreateFilledBuffer({ 0, 1, 2, 2, 3, 0 }); YTE::Vertex mVertex1; mVertex1.mPosition = { -0.5f, -0.5f, 0.0f, 1.0f }; mVertex1.mUVCoordinates = { 0.0f, 0.0f }; mVertex1.mNormal = { 0.0f, 0.0f, 1.0 }; YTE::Vertex mVertex2; mVertex2.mPosition = { 0.5f, -0.5f, 0.0f, 1.0f }; mVertex2.mUVCoordinates = { 1.0f, 0.0f }; mVertex2.mNormal = { 0.0f, 0.0f, 1.0 }; YTE::Vertex mVertex3; mVertex3.mPosition = { 0.5f, 0.5f, 0.0f, 1.0f }; mVertex3.mUVCoordinates = { 1.0f, 1.0f }; mVertex3.mNormal = { 0.0f, 0.0f, 1.0 }; YTE::Vertex mVertex4; mVertex4.mPosition = { -0.5f, 0.5f, 0.0f, 1.0f }; mVertex4.mUVCoordinates = { 0.0f, 1.0f }; mVertex4.mNormal = { 0.0f, 0.0f, 1.0 }; mQuadVerticies = self->CreateFilledBuffer({ mVertex1, mVertex2, mVertex3, mVertex4 }); } }
Renderer::Renderer(CCamera* m_camera, COGLContext* glContext, CConfigManager* confManager) : m_camera(m_camera), m_glContext(glContext), m_confManager(confManager) { { std::vector<float3> positions; positions.push_back(make_float3(536.419, 548.9, 431.274)); positions.push_back(make_float3(540.488, 548.9, 465.94)); positions.push_back(make_float3(419.977, 469.29, 559.3)); positions.push_back(make_float3(555.476, 471.466, 510.595)); positions.push_back(make_float3(438.946, 548.9, 506.097)); positions.push_back(make_float3(434.071, 501.603, 559.3)); positions.push_back(make_float3(452.146, 548.9, 529.52)); positions.push_back(make_float3(504.6, 509.978, 559.3)); std::vector<float3> normals; for (int i = 0; i < positions.size(); ++i) { normals.push_back(make_float3(0.f, 1.f, 0.f)); } SimpleBvh bvh(positions, normals, false); } m_cudaContext .reset(new cuda::CudaContext()); m_textureViewer .reset(new TextureViewer()); m_postProcess .reset(new Postprocess(m_confManager)); m_fullScreenQuad .reset(new FullScreenQuad()); m_shadowMap .reset(new CShadowMap(512)); m_experimentData .reset(new CExperimentData()); m_export .reset(new CExport()); m_depthBuffer.reset(new COGLTexture2D(m_camera->GetWidth(), m_camera->GetHeight(), GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, 1, false, "Renderer.m_pDepthBuffer")); m_testTexture.reset(new COGLTexture2D(m_camera->GetWidth(), m_camera->GetHeight(), GL_RGBA32F, GL_RGBA, GL_FLOAT, 1, false, "Renderer.m_pTestTexture")); m_gbuffer.reset(new CGBuffer(m_camera->GetWidth(), m_camera->GetHeight(), m_depthBuffer.get())); m_ubTransform.reset(new COGLUniformBuffer(sizeof(TRANSFORM), 0, GL_DYNAMIC_DRAW , "UBTransform" )); m_ubMaterial .reset(new COGLUniformBuffer(sizeof(MATERIAL), 0, GL_DYNAMIC_DRAW , "UBMaterial" )); m_ubLight .reset(new COGLUniformBuffer(sizeof(AVPL_STRUCT), 0, GL_DYNAMIC_DRAW , "UBLight" )); m_ubConfig .reset(new COGLUniformBuffer(sizeof(CONFIG), 0, GL_DYNAMIC_DRAW , "UBConfig" )); m_ubCamera .reset(new COGLUniformBuffer(sizeof(CAMERA), 0, GL_DYNAMIC_DRAW , "UBCamera" )); m_ubInfo .reset(new COGLUniformBuffer(sizeof(INFO), 0, GL_DYNAMIC_DRAW , "UBInfo" )); m_linearSampler .reset(new COGLSampler(GL_LINEAR, GL_LINEAR, GL_CLAMP, GL_CLAMP, "LinearSampler")); m_pointSampler .reset(new COGLSampler(GL_NEAREST, GL_NEAREST, GL_REPEAT, GL_REPEAT, "PointSampler")); m_shadowMapSampler .reset(new COGLSampler(GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, "ShadowMapSampler")); m_postProcessRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 1, 0)); m_errorRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 1, 0)); m_gatherShadowmapRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 4, 0)); m_gatherAntiradianceRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 4, 0)); m_normalizeShadowmapRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 3, m_depthBuffer.get())); m_normalizeAntiradianceRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 3, m_depthBuffer.get())); m_resultRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 1, m_depthBuffer.get())); m_lightDebugRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 1, m_depthBuffer.get())); m_cudaRenderTarget .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 4, 0)); m_cudaRenderTargetSum .reset(new CRenderTarget(m_camera->GetWidth(), m_camera->GetHeight(), 4, 0)); m_gatherProgram .reset(new CProgram("Shaders/Gather.vert" , "Shaders/Gather.frag" , "GatherProgram" )); m_normalizeProgram .reset(new CProgram("Shaders/Gather.vert" , "Shaders/Normalize.frag" , "NormalizeProgram" )); m_errorProgram .reset(new CProgram("Shaders/Gather.vert" , "Shaders/Error.frag" , "ErrorProgram" )); m_addProgram .reset(new CProgram("Shaders/Gather.vert" , "Shaders/Add.frag" , "AddProgram" )); m_createGBufferProgram .reset(new CProgram("Shaders/CreateGBuffer.vert" , "Shaders/CreateGBuffer.frag" , "CreateGBufferProgram" )); m_createSMProgram .reset(new CProgram("Shaders/CreateSM.vert" , "Shaders/CreateSM.frag" , "CreateSMProgram" )); m_gatherRadianceWithSMProgram .reset(new CProgram("Shaders/Gather.vert" , "Shaders/GatherRadianceWithSM.frag" , "GatherRadianceWithSMProgram" )); m_areaLightProgram .reset(new CProgram("Shaders/DrawAreaLight.vert" , "Shaders/DrawAreaLight.frag" , "AreaLightProgram" )); m_drawSphere .reset(new CProgram("Shaders/DrawSphere.vert" , "Shaders/DrawSphere.frag" , "DrawSphere" )); m_debugProgram .reset(new CProgram("Shaders/Debug.vert" , "Shaders/Debug.frag" , "Debug" )); m_scene.reset(new Scene(m_camera, m_confManager)); m_scene->LoadCornellBox(); m_avplShooter.reset(new AvplShooter(m_scene.get(), m_confManager)); m_imagePlane .reset(new CImagePlane(m_scene->GetCamera())); m_pathTracingIntegrator .reset(new CPathTracingIntegrator(m_scene.get(), m_imagePlane.get())); m_cpuTimer .reset(new CTimer(CTimer::CPU)); m_glTimer .reset(new CTimer(CTimer::OGL)); m_globalTimer .reset(new CTimer(CTimer::CPU)); m_resultTimer .reset(new CTimer(CTimer::CPU)); m_cpuFrameProfiler .reset(new CTimer(CTimer::CPU)); m_gpuFrameProfiler .reset(new CTimer(CTimer::OGL)); m_Finished = false; m_FinishedDirectLighting = false; m_FinishedIndirectLighting = false; m_FinishedDebug = false; m_ProfileFrame = false; m_NumAVPLsForNextDataExport = 1000; m_NumAVPLsForNextImageExport = 10000; m_NumAVPLs = 0; m_NumPathsDebug = 0; m_ClearLighting = false; m_ClearAccumulationBuffer = false; BindSamplers(); UpdateUniformBuffers(); time(&m_StartTime); InitDebugLights(); ClearAccumulationBuffer(); m_globalTimer->Start(); m_cudaTargetTexture.reset(new COGLTexture2D(m_camera->GetWidth(), m_camera->GetWidth(), GL_RGBA32F, GL_RGBA, GL_FLOAT, 1, false, "m_cudaTarget")); m_cudaGather.reset(new CudaGather(m_camera, m_gbuffer->GetPositionTextureWS()->GetResourceIdentifier(), m_gbuffer->GetNormalTexture()->GetResourceIdentifier(), m_cudaRenderTarget->GetTarget(0)->GetResourceIdentifier(), m_cudaRenderTarget->GetTarget(1)->GetResourceIdentifier(), m_cudaRenderTarget->GetTarget(2)->GetResourceIdentifier(), m_scene->GetMaterialBuffer()->getMaterials(), m_ubTransform.get(), m_confManager)); }
void GraphicsSystem::VulkanRender() { auto self = mPlatformSpecificData.Get<VulkanContext>(); if (mObjectsBufferSize < mObjects.size()) { SetupObjectBuffer(); SetupDrawing(); } auto bufferSize = static_cast<u32>(mObjects.size() * sizeof(Object)); //for (auto &object : mObjects) //{ // glm::mat4 objectToWorld = glm::translate(glm::mat4(), object.mTranslation); // // objectToWorld = glm::rotate(objectToWorld, object.mRotation.x, glm::vec3(1.0, 0.0, 0.0)); // objectToWorld = glm::rotate(objectToWorld, object.mRotation.y, glm::vec3(0.0, 1.0, 0.0)); // objectToWorld = glm::rotate(objectToWorld, object.mRotation.z, glm::vec3(0.0, 0.0, 1.0)); // // objectToWorld = glm::scale(objectToWorld, object.mScale); // object.mTransform = objectToWorld; //} auto objectsBufferPtr = static_cast<Object*>(self->mLogicalDevice.mapMemory(mObjectsBuffer.mMemory, 0, bufferSize)); memcpy(objectsBufferPtr, mObjects.data(), bufferSize); self->mLogicalDevice.unmapMemory(mObjectsBuffer.mMemory); const float zoomSpeed = 0.15f; const float rotationSpeed = 1.25f; // Update rotation auto &mouse = mEngine->mPrimaryWindow->mMouse; if (true == mouse.mLeftMouseDown) { self->mRotation.x += (mMousePosition.y - (float)mouse.mY) * rotationSpeed; self->mRotation.y -= (mMousePosition.x - (float)mouse.mX) * rotationSpeed; mMousePosition.x = mouse.mX; mMousePosition.y = mouse.mY; } // Update zoom auto zoom = self->mZoom; self->mZoom += mEngine->mPrimaryWindow->mMouse.mWheelDelta * zoomSpeed; if (zoom != self->mZoom || true == mouse.mLeftMouseDown) { self->UpdateUniformBuffers(true); } vk::SemaphoreCreateInfo semaphoreCreateInfo = vk::SemaphoreCreateInfo(); auto presentCompleteSemaphore = self->mLogicalDevice.createSemaphore(semaphoreCreateInfo); auto renderingCompleteSemaphore = self->mLogicalDevice.createSemaphore(semaphoreCreateInfo); auto result = self->mLogicalDevice.acquireNextImageKHR(self->mSwapChain, UINT64_MAX, presentCompleteSemaphore, VK_NULL_HANDLE, &self->mCurrentDrawBuffer); checkVulkanResult(result, "Could not acquireNextImageKHR."); // present: vk::Fence renderFence = self->mLogicalDevice.createFence(vk::FenceCreateInfo()); vk::PipelineStageFlags waitStageMash = { vk::PipelineStageFlagBits::eBottomOfPipe }; vk::SubmitInfo submitInfo = {}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &presentCompleteSemaphore; submitInfo.pWaitDstStageMask = &waitStageMash; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &self->mDrawCommandBuffers[self->mCurrentDrawBuffer]; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &renderingCompleteSemaphore; self->mQueue.submit(submitInfo, renderFence); self->mLogicalDevice.waitForFences(renderFence, true, UINT64_MAX); self->mLogicalDevice.destroyFence(renderFence); vk::PresentInfoKHR presentInfo = {}; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = &renderingCompleteSemaphore; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = &self->mSwapChain; presentInfo.pImageIndices = &self->mCurrentDrawBuffer; self->mQueue.presentKHR(presentInfo); self->mLogicalDevice.destroySemaphore(presentCompleteSemaphore); self->mLogicalDevice.destroySemaphore(renderingCompleteSemaphore); }
void Renderer::Render() { if(m_ClearLighting) ClearLighting(); if(m_ClearAccumulationBuffer) ClearAccumulationBuffer(); CTimer frameTimer(CTimer::OGL); CTimer timer(CTimer::OGL); if(m_ProfileFrame) { std::cout << std::endl; std::cout << "Profile frame --------------- " << std::endl; std::cout << std::endl; frameTimer.Start(); timer.Start(); } SetUpRender(); if(m_ProfileFrame) timer.Stop("set up render"); if(m_ProfileFrame) timer.Start(); UpdateUniformBuffers(); if(m_ProfileFrame) timer.Stop("update ubs"); if(m_CurrentPathAntiradiance == 0 && m_CurrentPathShadowmap == 0) { m_experimentData->Init("test", "nois.data"); m_experimentData->MaxTime(450); m_globalTimer->Start(); m_resultTimer->Start(); m_glTimer->Start(); CreateGBuffer(); m_cudaGather->rebuildVisiblePointsBvh(); } if (m_confManager->GetConfVars()->drawGBufferTextures) { int border = 10; int width = (m_camera->GetWidth() - 4 * border) / 2; int height = (m_camera->GetHeight() - 4 * border) / 2; m_textureViewer->drawTexture(m_gbuffer->GetNormalTexture(), border, border, width, height); m_textureViewer->drawTexture(m_gbuffer->GetPositionTextureWS(), 3 * border + width, border, width, height); m_textureViewer->drawTexture(m_normalizeAntiradianceRenderTarget->GetTarget(2), border, 3 * border + height, width, height); m_textureViewer->drawTexture(m_depthBuffer.get(), 3 * border + width, 3 * border + height, width, height); return; } std::vector<Avpl> avpls_shadowmap; std::vector<Avpl> avpls_antiradiance; if(m_ProfileFrame) timer.Start(); //GetAVPLs(avpls_shadowmap, avpls_antiradiance); m_avplShooter->shoot(avpls_shadowmap, avpls_antiradiance, m_confManager->GetConfVars()->NumAVPLsPerFrame); m_CurrentPathAntiradiance += m_confManager->GetConfVars()->NumAVPLsPerFrame; if(m_ProfileFrame) timer.Stop("get avpls"); if(m_ProfileFrame) timer.Start(); if (m_confManager->GetConfVars()->gatherWithCuda) { if (avpls_antiradiance.size() > 0) { m_cudaGather->run(avpls_antiradiance, m_camera->GetPosition(), m_sceneProbe.get(), m_scene->getSceneExtent(), m_ProfileFrame); Add(m_gatherAntiradianceRenderTarget.get(), m_cudaRenderTarget.get()); } if(m_ProfileFrame) timer.Stop("gather"); if(m_ProfileFrame) timer.Start(); } else { Gather(avpls_shadowmap, avpls_antiradiance); if(m_ProfileFrame) timer.Stop("gather"); if(m_ProfileFrame) timer.Start(); } Normalize(m_normalizeShadowmapRenderTarget.get(), m_gatherShadowmapRenderTarget.get(), m_CurrentPathShadowmap); Normalize(m_normalizeAntiradianceRenderTarget.get(), m_gatherAntiradianceRenderTarget.get(), m_CurrentPathAntiradiance); if(m_ProfileFrame) timer.Stop("normalize"); if(m_ProfileFrame) timer.Start(); if(m_confManager->GetConfVars()->LightingMode == 2) { drawAreaLight(m_normalizeShadowmapRenderTarget.get(), glm::vec3(0.f, 0.f, 0.f)); drawAreaLight(m_normalizeAntiradianceRenderTarget.get(), glm::vec3(0.f, 0.f, 0.f)); } else { drawAreaLight(m_normalizeShadowmapRenderTarget.get(), m_scene->getAreaLight()->getRadiance()); } SetTransformToCamera(); Add(m_resultRenderTarget.get(), m_normalizeAntiradianceRenderTarget.get(), m_normalizeShadowmapRenderTarget.get()); if (m_confManager->GetConfVars()->UseDebugMode) { if (m_confManager->GetConfVars()->DrawClusterLights) { CRenderTargetLock lock(m_resultRenderTarget.get()); PointCloud pc(m_cudaGather->getVisiblePointsBvh()->centerPositions, m_cudaGather->getVisiblePointsBvh()->colors, m_ubTransform.get(), m_confManager->GetConfVars()->lightRadiusScale * m_scene->getSceneExtent() / 100.f); pc.Draw(); //m_cudaGather->getPointCloud()->Draw(); } if (m_confManager->GetConfVars()->DrawClusterAABBs) { CRenderTargetLock lock(m_resultRenderTarget.get()); AABBCloud aabb(m_cudaGather->getVisiblePointsBvh()->clusterMin, m_cudaGather->getVisiblePointsBvh()->clusterMax, m_ubTransform.get()); aabb.Draw(); //m_cudaGather->getAABBCloud()->Draw(); } if (m_confManager->GetConfVars()->DrawLights) { CRenderTargetLock lock(m_resultRenderTarget.get()); m_pointCloud->Draw(); } if (m_sceneProbe) { m_sceneProbe->draw(m_resultRenderTarget.get(), m_debugProgram.get(), m_ubTransform.get(), m_camera); m_pointCloud->Draw(); } } DrawDebug(); if(m_ProfileFrame) timer.Stop("draw debug"); m_postProcess->postprocess(m_resultRenderTarget->GetTarget(0), m_postProcessRenderTarget.get()); m_textureViewer->drawTexture(m_postProcessRenderTarget->GetTarget(0), 0, 0, m_camera->GetWidth(), m_camera->GetHeight()); m_NumAVPLs += (int)avpls_antiradiance.size(); m_NumAVPLs += (int)avpls_shadowmap.size(); if(m_ProfileFrame) timer.Start(); avpls_antiradiance.clear(); avpls_shadowmap.clear(); if(m_ProfileFrame) timer.Stop("clear avpls"); CheckExport(); m_Frame++; if(m_ProfileFrame) frameTimer.Stop("frame time"); m_ProfileFrame = false; m_FinishedDebug = true; }