static void TryChoosePhysDev(alloc* Scratch, bool discreteOnly, VkPhysicalDevice* physicalDevices, uint32_t physicalDevicesCount, const char** deviceExtensions, uint32_t deviceExtensionsCount) { for (uint32_t idevice = 0; idevice < physicalDevicesCount; ++idevice) { VkPhysicalDevice physDev = physicalDevices[idevice]; VkPhysicalDeviceProperties physDevProps; vkGetPhysicalDeviceProperties(physDev, &physDevProps); if (discreteOnly) { if (physDevProps.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { LOG("Skipped device: non discrete GPU"); continue; } } VkPhysicalDeviceMemoryProperties physDevMemProps; vkGetPhysicalDeviceMemoryProperties(physDev, &physDevMemProps); uint32_t physDevExtensionsCount; vkEnumerateDeviceExtensionProperties(physDev, nullptr, &physDevExtensionsCount, nullptr); VkExtensionProperties* physDevExtensions = PUSH_ALLOC(Scratch, VkExtensionProperties, physDevExtensionsCount); vkEnumerateDeviceExtensionProperties(physDev, nullptr, &physDevExtensionsCount, physDevExtensions); uint32_t missingExtensionsCount = deviceExtensionsCount; for (uint32_t i = 0; i < physDevExtensionsCount; ++i) { for (uint32_t j = 0; j < deviceExtensionsCount; ++j) { if (strcmp(physDevExtensions[i].extensionName, deviceExtensions[j]) == 0) { LOG("Found device extension: %s", deviceExtensions[j]); --missingExtensionsCount; if (missingExtensionsCount == 0) break; } } if (missingExtensionsCount == 0) break; } if (missingExtensionsCount > 0) { LOG("Skipped device: missing extensions %d", missingExtensionsCount); for (uint32_t i = 0; i < deviceExtensionsCount; ++i) { bool found = false; for (uint32_t j = 0; j < physDevExtensionsCount; ++j) { if (strcmp(physDevExtensions[j].extensionName, deviceExtensions[i]) == 0) { found = true; break; } } if (!found) { LOG(" %s", deviceExtensions[i]); } } continue; } uint32_t queueFamiliesCount; vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueFamiliesCount, nullptr); VkQueueFamilyProperties* queueFamilies = PUSH_ALLOC(Scratch, VkQueueFamilyProperties, queueFamiliesCount); vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueFamiliesCount, queueFamilies); uint32_t graphicsQueueIndex = UINT32_MAX; uint32_t transferQueueIndex = UINT32_MAX; for (size_t i = 0; i < queueFamiliesCount; ++i) { VkQueueFamilyProperties* queueFamily = &queueFamilies[i]; if (queueFamily->queueCount == 0) continue; if (queueFamily->queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (graphicsQueueIndex == UINT32_MAX) graphicsQueueIndex = i; continue; } if (queueFamily->queueFlags & VK_QUEUE_COMPUTE_BIT) continue; if (queueFamily->queueFlags & VK_QUEUE_TRANSFER_BIT) continue; } if (graphicsQueueIndex == UINT32_MAX) { LOG("Skipped device: no graphics queue"); continue; } rhi->physDev = physDev; rhi->physDevProps = physDevProps; rhi->physDevMemProps = physDevMemProps; rhi->graphicsQueue.queueFamilyIndex = graphicsQueueIndex; break; } } static void Rhi_Bootstrap(alloc* Scratch, rhi_init_desc* Config) { uint8_t* ScratchMark = Scratch->at; VulkanLoadGlobalProcs(); rhi = PUSH_ALLOC(&PermanentAlloc, rhi_state, 1); rhi->recreateSwapchain = true; rhi->flags = Config->flags; rhi->limits = Config->limits; rhi->CmdLists = PUSH_ALLOC(&PermanentAlloc, rhi_cmdlist_data, rhi->limits.CmdListsCount); rhi->Buffers = PUSH_ALLOC(&PermanentAlloc, rhi_buffer_data, rhi->limits.BuffersCount); rhi->ConstantBufferViews = PUSH_ALLOC(&PermanentAlloc, rhi_buffer_view_data, rhi->limits.ConstantBufferViewsCount); rhi->Textures = PUSH_ALLOC(&PermanentAlloc, rhi_texture_data, rhi->limits.TexturesCount); rhi->SampledTextureViews = PUSH_ALLOC(&PermanentAlloc, rhi_texture_view_data, rhi->limits.SampledTextureViewsCount); rhi->DepthStencilViews = PUSH_ALLOC(&PermanentAlloc, rhi_texture_view_data, rhi->limits.DepthStencilViewsCount); rhi->RenderTargetViews = PUSH_ALLOC(&PermanentAlloc, rhi_texture_view_data, rhi->limits.RenderTargetViewsCount); rhi->Samplers = PUSH_ALLOC(&PermanentAlloc, rhi_sampler_data, rhi->limits.SamplersCount); rhi->GraphicsPipelines = PUSH_ALLOC(&PermanentAlloc, rhi_graphics_pipeline_data, rhi->limits.GraphicsPipelinesCount); rhi->Shaders = PUSH_ALLOC(&PermanentAlloc, rhi_shader_data, rhi->limits.ShadersCount); VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "nyla"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "nyla"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_4; const char** EnabledInstanceExtensions = PUSH_ALLOC(Scratch, const char*, 5); uint32_t EnabledInstanceExtensionsCount = 0; EnabledInstanceExtensions[EnabledInstanceExtensionsCount++] = VK_KHR_SURFACE_EXTENSION_NAME; #if defined(__linux__) EnabledInstanceExtensions[EnabledInstanceExtensionsCount++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME; #else EnabledInstanceExtensions[EnabledInstanceExtensionsCount++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME; #endif const char** EnabledInstanceLayers = PUSH_ALLOC(Scratch, const char*, 1); uint32_t EnabledInstanceLayersCount = 0; #if RHI_VALIDATIONS EnabledInstanceLayers[EnabledInstanceLayersCount++] = "VK_LAYER_KHRONOS_validation"; #endif #if RHI_VALIDATIONS VkValidationFeaturesEXT validationFeatures{}; validationFeatures.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; validationFeatures.enabledValidationFeatureCount = 0; validationFeatures.pEnabledValidationFeatures = nullptr; validationFeatures.disabledValidationFeatureCount = 0; validationFeatures.pDisabledValidationFeatures = nullptr; VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreateInfo{}; debugMessengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; debugMessengerCreateInfo.pNext = &validationFeatures; debugMessengerCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; debugMessengerCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; debugMessengerCreateInfo.pfnUserCallback = DebugMessengerCallback; debugMessengerCreateInfo.pUserData = nullptr; #endif uint32_t instanceExtensionsCount; vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionsCount, nullptr); VkExtensionProperties* instanceExtensions = PUSH_ALLOC(Scratch, VkExtensionProperties, instanceExtensionsCount); vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionsCount, instanceExtensions); LOG("\n%" PRIu32 " Instance Extensions available", instanceExtensionsCount); for (uint32_t i = 0; i < instanceExtensionsCount; ++i) { LOG("%s", instanceExtensions[i].extensionName); } uint32_t instanceLayersCount; vkEnumerateInstanceLayerProperties(&instanceLayersCount, nullptr); VkLayerProperties* instanceLayers = PUSH_ALLOC(Scratch, VkLayerProperties, instanceLayersCount); vkEnumerateInstanceLayerProperties(&instanceLayersCount, instanceLayers); LOG("\n%" PRIu32 " Layers available", instanceLayersCount); for (uint32_t i = 0; i < instanceLayersCount; ++i) { VkLayerProperties* layer = &instanceLayers[i]; LOG(" %s", layer->layerName); uint32_t layerExtensionsCount; vkEnumerateInstanceExtensionProperties(layer->layerName, &layerExtensionsCount, nullptr); VkExtensionProperties* layerExtensions = PUSH_ALLOC(Scratch, VkExtensionProperties, layerExtensionsCount); vkEnumerateInstanceExtensionProperties(layer->layerName, &layerExtensionsCount, layerExtensions); for (uint32_t j = 0; j < layerExtensionsCount; j++) { LOG(" %s", layerExtensions[j].extensionName); } } VkDebugUtilsMessengerEXT debugMessenger{}; VkInstanceCreateInfo instanceCreateInfo{}; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceCreateInfo.pApplicationInfo = &appInfo; #if RHI_VALIDATIONS #if 0 // TODO: fix this branch InlineVec_Append(validationEnabledFeatures, VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT); InlineVec_Append(validationEnabledFeatures, VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT); InlineVec_Append(validationEnabledFeatures, VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT); InlineVec_Append(validationEnabledFeatures, VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT); validationFeatures.enabledValidationFeatureCount = validationEnabledFeatures.size; InlineVec_Append(validationDisabledFeatures, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT); validationFeatures.disabledValidationFeatureCount = validationEnabledFeatures.size; #endif instanceCreateInfo.pNext = &debugMessengerCreateInfo; EnabledInstanceExtensions[EnabledInstanceExtensionsCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; EnabledInstanceExtensions[EnabledInstanceExtensionsCount++] = VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME; #endif instanceCreateInfo.enabledLayerCount = EnabledInstanceLayersCount; instanceCreateInfo.ppEnabledLayerNames = EnabledInstanceLayers; instanceCreateInfo.enabledExtensionCount = EnabledInstanceExtensionsCount; instanceCreateInfo.ppEnabledExtensionNames = EnabledInstanceExtensions; VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &rhi->instance)); VulkanLoadInstanceProcs(rhi->instance); #if RHI_VALIDATIONS VK_CHECK(vkCreateDebugUtilsMessengerEXT(rhi->instance, &debugMessengerCreateInfo, nullptr, &debugMessenger)); #endif uint32_t physicalDevicesCount = 0; VK_CHECK(vkEnumeratePhysicalDevices(rhi->instance, &physicalDevicesCount, nullptr)); VkPhysicalDevice* physicalDevices = PUSH_ALLOC(Scratch, VkPhysicalDevice, physicalDevicesCount); VK_CHECK(vkEnumeratePhysicalDevices(rhi->instance, &physicalDevicesCount, physicalDevices)); const char** deviceExtensions = PUSH_ALLOC(Scratch, const char*, 5); uint32_t deviceExtensionsCount = 0; deviceExtensions[deviceExtensionsCount++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; deviceExtensions[deviceExtensionsCount++] = VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME; deviceExtensions[deviceExtensionsCount++] = VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME; #if 0 deviceExtensions[deviceExtensionsCount++] = VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME; #endif TryChoosePhysDev(Scratch, true, physicalDevices, physicalDevicesCount, deviceExtensions, deviceExtensionsCount); if (!rhi->physDev) TryChoosePhysDev(Scratch, false, physicalDevices, physicalDevicesCount, deviceExtensions, deviceExtensionsCount); ASSERT(rhi->physDev); LOG("Picked device: %s", rhi->physDevProps.deviceName); VkDeviceQueueCreateInfo queueCreateInfo{}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = rhi->graphicsQueue.queueFamilyIndex; queueCreateInfo.queueCount = 1; float queuePriority = 1.f; queueCreateInfo.pQueuePriorities = &queuePriority; VkPhysicalDeviceVulkan14Features v14{}; v14.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES; VkPhysicalDeviceVulkan13Features v13{}; v13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; v13.pNext = &v14; v13.shaderDemoteToHelperInvocation = true; v13.synchronization2 = true; v13.dynamicRendering = true; VkPhysicalDeviceVulkan12Features v12{}; v12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; v12.pNext = &v13; v12.descriptorIndexing = true; v12.shaderSampledImageArrayNonUniformIndexing = true; v12.descriptorBindingSampledImageUpdateAfterBind = true; v12.descriptorBindingUpdateUnusedWhilePending = true; v12.descriptorBindingPartiallyBound = true; v12.descriptorBindingVariableDescriptorCount = true; v12.runtimeDescriptorArray = true; v12.timelineSemaphore = true; VkPhysicalDeviceVulkan11Features v11{}; v11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; v11.pNext = &v12; VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT vertexInputDynamicStateFeatures{}; vertexInputDynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT; vertexInputDynamicStateFeatures.pNext = &v11; vertexInputDynamicStateFeatures.vertexInputDynamicState = true; VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR fifoLatestReadyFeatures{}; fifoLatestReadyFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR; fifoLatestReadyFeatures.pNext = &vertexInputDynamicStateFeatures; fifoLatestReadyFeatures.presentModeFifoLatestReady = true; VkPhysicalDeviceFeatures2 features{}; features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features.pNext = &fifoLatestReadyFeatures; features.features = {}; VkDeviceCreateInfo deviceCreateInfo{}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.pNext = &features; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; deviceCreateInfo.enabledExtensionCount = deviceExtensionsCount; deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions; VK_CHECK(vkCreateDevice(rhi->physDev, &deviceCreateInfo, nullptr, &rhi->dev)); VulkanLoadDeviceProcs(rhi->dev); vkGetDeviceQueue(rhi->dev, rhi->graphicsQueue.queueFamilyIndex, 0, &rhi->graphicsQueue.queue); { // graphics queue VkCommandPoolCreateInfo commandPoolCreateInfo{}; commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; commandPoolCreateInfo.queueFamilyIndex = rhi->graphicsQueue.queueFamilyIndex; VK_CHECK(vkCreateCommandPool(rhi->dev, &commandPoolCreateInfo, nullptr, &rhi->graphicsQueue.cmdPool)); rhi->graphicsQueue.timeline = VulkanCreateTimelineSemaphore(0); rhi->graphicsQueue.timelineNext = 1; rhi->graphicsQueue.cmd = Rhi_CreateCmdList("Graphics Command List", QueueType_Graphics); } { VkSemaphoreCreateInfo semaphoreCreateInfo{}; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; VK_CHECK(vkCreateSemaphore(rhi->dev, &semaphoreCreateInfo, nullptr, &rhi->SwapChainAcquireSemaphore)); } { // surface #if defined(__linux__) VkXcbSurfaceCreateInfoKHR surfaceCreateInfo{}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; surfaceCreateInfo.connection = xcb_connect(nullptr, nullptr); surfaceCreateInfo.window = X11->Window; VK_CHECK(vkCreateXcbSurfaceKHR(rhi->instance, &surfaceCreateInfo, rhi->vkAlloc, &rhi->surface)); #else VkWin32SurfaceCreateInfoKHR surfaceCreateInfo{}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; surfaceCreateInfo.hinstance = S->hInstance; surfaceCreateInfo.hwnd = S->hWnd; VK_CHECK(vkCreateWin32SurfaceKHR(rhi->instance, &surfaceCreateInfo, rhi->vkAlloc, &rhi->surface)); #endif } CreateSwapchain(Scratch); { // descriptor pool VkDescriptorPoolSize* descriptorPoolSizes = PUSH_ALLOC(Scratch, VkDescriptorPoolSize, 4); uint32_t descriptorPoolSizesCount = 0; descriptorPoolSizes[descriptorPoolSizesCount].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; descriptorPoolSizes[descriptorPoolSizesCount].descriptorCount = 16; ++descriptorPoolSizesCount; descriptorPoolSizes[descriptorPoolSizesCount].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; descriptorPoolSizes[descriptorPoolSizesCount].descriptorCount = 16; ++descriptorPoolSizesCount; descriptorPoolSizes[descriptorPoolSizesCount].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; descriptorPoolSizes[descriptorPoolSizesCount].descriptorCount = rhi->limits.SampledTextureViewsCount; ++descriptorPoolSizesCount; descriptorPoolSizes[descriptorPoolSizesCount].type = VK_DESCRIPTOR_TYPE_SAMPLER; descriptorPoolSizes[descriptorPoolSizesCount].descriptorCount = rhi->limits.SamplersCount; ++descriptorPoolSizesCount; VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{}; descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptorPoolCreateInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; descriptorPoolCreateInfo.maxSets = 16; descriptorPoolCreateInfo.poolSizeCount = descriptorPoolSizesCount; descriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes; vkCreateDescriptorPool(rhi->dev, &descriptorPoolCreateInfo, nullptr, &rhi->descriptorPool); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)rhi->descriptorPool, "Descriptor pools"); } { // constants VkDescriptorSetLayoutBinding* descriptorLayoutBindings = PUSH_ALLOC(Scratch, VkDescriptorSetLayoutBinding, 3); uint32_t descriptorLayoutBindingsCount = 0; descriptorLayoutBindings[descriptorLayoutBindingsCount].binding = 0; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorCount = 1; descriptorLayoutBindings[descriptorLayoutBindingsCount].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; ++descriptorLayoutBindingsCount; descriptorLayoutBindings[descriptorLayoutBindingsCount].binding = 1; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorCount = 1; descriptorLayoutBindings[descriptorLayoutBindingsCount].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; ++descriptorLayoutBindingsCount; descriptorLayoutBindings[descriptorLayoutBindingsCount].binding = 2; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; descriptorLayoutBindings[descriptorLayoutBindingsCount].descriptorCount = 1; descriptorLayoutBindings[descriptorLayoutBindingsCount].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; ++descriptorLayoutBindingsCount; VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutCreateInfo.bindingCount = descriptorLayoutBindingsCount; descriptorSetLayoutCreateInfo.pBindings = descriptorLayoutBindings; VK_CHECK(vkCreateDescriptorSetLayout(rhi->dev, &descriptorSetLayoutCreateInfo, rhi->vkAlloc, &rhi->constantsDescriptorTable.layout)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)rhi->constantsDescriptorTable.layout, "Constants Descriptor Set Layout"); VkDescriptorSetAllocateInfo descriptorSetAllocInfo{}; descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; descriptorSetAllocInfo.descriptorPool = rhi->descriptorPool; descriptorSetAllocInfo.descriptorSetCount = 1; descriptorSetAllocInfo.pSetLayouts = &rhi->constantsDescriptorTable.layout; VK_CHECK(vkAllocateDescriptorSets(rhi->dev, &descriptorSetAllocInfo, &rhi->constantsDescriptorTable.set)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)rhi->constantsDescriptorTable.set, "Constants Descriptor Set"); uint64_t BufferSize = 0; BufferSize += CbvOffset(rhi->limits.FrameConstantSize); BufferSize += rhi->limits.MaxPassCount * CbvOffset(rhi->limits.PassConstantSize); BufferSize += rhi->limits.MaxDrawCount * CbvOffset(rhi->limits.DrawConstantSize); LOG("Constants Buffer Size: %" PRIu64 "kb", CEIL_DIV(BufferSize, 1 << 10)); rhi->constantsUniformBuffer = Rhi_CreateBuffer("Draw Constants", BufferSize, BufferUsage_Uniform, MemoryUsage_CpuToGpu); VkBuffer vulkanBuffer = ((rhi_buffer_data*)rhi->constantsUniformBuffer)->buffer; VkDescriptorBufferInfo* bufferInfos = PUSH_ALLOC(Scratch, VkDescriptorBufferInfo, 3); uint32_t bufferInfosCount = 0; bufferInfos[bufferInfosCount].buffer = vulkanBuffer; bufferInfos[bufferInfosCount].range = CbvOffset(rhi->limits.FrameConstantSize); ++bufferInfosCount; bufferInfos[bufferInfosCount].buffer = vulkanBuffer; bufferInfos[bufferInfosCount].range = CbvOffset(rhi->limits.PassConstantSize); ++bufferInfosCount; bufferInfos[bufferInfosCount].buffer = vulkanBuffer; bufferInfos[bufferInfosCount].range = CbvOffset(rhi->limits.DrawConstantSize); ++bufferInfosCount; VkWriteDescriptorSet* descriptorWrites = PUSH_ALLOC(Scratch, VkWriteDescriptorSet, bufferInfosCount); for (uint32_t i = 0; i < bufferInfosCount; ++i) { VkDescriptorBufferInfo* bufferInfo = &bufferInfos[i]; descriptorWrites[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrites[i].dstSet = rhi->constantsDescriptorTable.set; descriptorWrites[i].dstBinding = i; descriptorWrites[i].descriptorCount = 1; descriptorWrites[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; descriptorWrites[i].pBufferInfo = bufferInfo; } vkUpdateDescriptorSets(rhi->dev, bufferInfosCount, descriptorWrites, 0, nullptr); } { // textures VkDescriptorBindingFlags bindingFlags = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo{}; bindingFlagsCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO; bindingFlagsCreateInfo.bindingCount = 1; bindingFlagsCreateInfo.pBindingFlags = &bindingFlags; VkDescriptorSetLayoutBinding descriptorLayoutBinding{}; descriptorLayoutBinding.binding = 0; descriptorLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; descriptorLayoutBinding.descriptorCount = rhi->limits.SampledTextureViewsCount; descriptorLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutCreateInfo.pNext = &bindingFlagsCreateInfo; descriptorSetLayoutCreateInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; descriptorSetLayoutCreateInfo.bindingCount = 1; descriptorSetLayoutCreateInfo.pBindings = &descriptorLayoutBinding; VK_CHECK(vkCreateDescriptorSetLayout(rhi->dev, &descriptorSetLayoutCreateInfo, rhi->vkAlloc, &rhi->texturesDescriptorTable.layout)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)rhi->texturesDescriptorTable.layout, "Textures Descriptor Set Layout"); VkDescriptorSetAllocateInfo descriptorSetAllocInfo{}; descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; descriptorSetAllocInfo.descriptorPool = rhi->descriptorPool; descriptorSetAllocInfo.descriptorSetCount = 1; descriptorSetAllocInfo.pSetLayouts = &rhi->texturesDescriptorTable.layout; VK_CHECK(vkAllocateDescriptorSets(rhi->dev, &descriptorSetAllocInfo, &rhi->texturesDescriptorTable.set)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)rhi->texturesDescriptorTable.set, "Textures Descriptor Set"); } { // samplers VkDescriptorBindingFlags bindingFlags = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo{}; bindingFlagsCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO; bindingFlagsCreateInfo.bindingCount = 1; bindingFlagsCreateInfo.pBindingFlags = &bindingFlags; VkDescriptorSetLayoutBinding descriptorLayoutBinding{}; descriptorLayoutBinding.binding = 0; descriptorLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; descriptorLayoutBinding.descriptorCount = rhi->limits.SamplersCount; descriptorLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutCreateInfo.pNext = &bindingFlagsCreateInfo; descriptorSetLayoutCreateInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; descriptorSetLayoutCreateInfo.bindingCount = 1; descriptorSetLayoutCreateInfo.pBindings = &descriptorLayoutBinding; VK_CHECK(vkCreateDescriptorSetLayout(rhi->dev, &descriptorSetLayoutCreateInfo, rhi->vkAlloc, &rhi->SamplersDescriptorTable.layout)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)rhi->SamplersDescriptorTable.layout, "Samplers Descriptor Set Layout"); VkDescriptorSetAllocateInfo descriptorSetAllocInfo{}; descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; descriptorSetAllocInfo.descriptorPool = rhi->descriptorPool; descriptorSetAllocInfo.descriptorSetCount = 1; descriptorSetAllocInfo.pSetLayouts = &rhi->SamplersDescriptorTable.layout; VK_CHECK(vkAllocateDescriptorSets(rhi->dev, &descriptorSetAllocInfo, &rhi->SamplersDescriptorTable.set)); VulkanNameHandle(VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)rhi->SamplersDescriptorTable.set, "Samplers Descriptor Set"); } Scratch->at = ScratchMark; }