public VkResourceCache(VkDevice device, VkSamplerState defaultSamplerState)
        {
            _device = device;
            _defaultSamplerState = defaultSamplerState;

            VkDescriptorPoolSize *sizes = stackalloc VkDescriptorPoolSize[3];

            sizes[0].type            = VkDescriptorType.UniformBuffer;
            sizes[0].descriptorCount = 50000;
            sizes[1].type            = VkDescriptorType.SampledImage;
            sizes[1].descriptorCount = 15000;
            sizes[2].type            = VkDescriptorType.Sampler;
            sizes[2].descriptorCount = 15000;

            VkDescriptorPoolCreateInfo descriptorPoolCI = VkDescriptorPoolCreateInfo.New();

            descriptorPoolCI.flags         = VkDescriptorPoolCreateFlags.FreeDescriptorSet;
            descriptorPoolCI.maxSets       = 15000;
            descriptorPoolCI.pPoolSizes    = sizes;
            descriptorPoolCI.poolSizeCount = 3;

            VkResult result = vkCreateDescriptorPool(_device, ref descriptorPoolCI, null, out _descriptorPool);

            CheckResult(result);
        }
        private VkDescriptorSet CreateNewDescriptorSet(ref VkDescriptorSetCacheKey cacheKey)
        {
            {
                VkDescriptorSetAllocateInfo descriptorSetAI = VkDescriptorSetAllocateInfo.New();
                descriptorSetAI.descriptorPool     = _descriptorPool;
                descriptorSetAI.descriptorSetCount = 1;
                VkDescriptorSetLayout layout = cacheKey.ShaderResourceBindingSlots.DescriptorSetLayout;
                descriptorSetAI.pSetLayouts = &layout;
                VkResult result = vkAllocateDescriptorSets(_device, ref descriptorSetAI, out VkDescriptorSet descriptorSet);
                CheckResult(result);

                int resourceCount = cacheKey.ShaderResourceBindingSlots.Resources.Length;
                VkWriteDescriptorSet[]  descriptorWrites = new VkWriteDescriptorSet[resourceCount];
                VkDescriptorBufferInfo *bufferInfos      = stackalloc VkDescriptorBufferInfo[resourceCount]; // TODO: Fix this.
                VkDescriptorImageInfo * imageInfos       = stackalloc VkDescriptorImageInfo[resourceCount];  // TODO: Fix this.

                for (uint binding = 0; binding < resourceCount; binding++)
                {
                    descriptorWrites[binding].sType           = VkStructureType.WriteDescriptorSet;
                    descriptorWrites[binding].descriptorCount = 1;
                    descriptorWrites[binding].dstBinding      = binding;
                    descriptorWrites[binding].dstSet          = descriptorSet;

                    ShaderResourceDescription resource = cacheKey.ShaderResourceBindingSlots.Resources[binding];
                    switch (resource.Type)
                    {
                    case ShaderResourceType.ConstantBuffer:
                    {
                        descriptorWrites[binding].descriptorType = VkDescriptorType.UniformBuffer;
                        VkConstantBuffer cb = cacheKey.ConstantBuffers[binding];
                        if (cb == null)
                        {
                            throw new VeldridException($"No constant buffer bound to required binding slot {binding}.");
                        }
                        VkDescriptorBufferInfo *cbInfo = &bufferInfos[binding];
                        cbInfo->buffer = cb.DeviceBuffer;
                        cbInfo->offset = 0;
                        cbInfo->range  = (ulong)resource.DataSizeInBytes;
                        descriptorWrites[binding].pBufferInfo = cbInfo;
                        break;
                    }

                    case ShaderResourceType.Texture:
                    {
                        descriptorWrites[binding].descriptorType = VkDescriptorType.SampledImage;
                        VkShaderTextureBinding textureBinding = cacheKey.TextureBindings[binding];
                        if (textureBinding == null)
                        {
                            throw new VeldridException($"No texture bound to required binding slot {binding}.");
                        }
                        VkDescriptorImageInfo *imageInfo = &imageInfos[binding];
                        imageInfo->imageLayout = textureBinding.ImageLayout;
                        imageInfo->imageView   = textureBinding.ImageView;
                        descriptorWrites[binding].pImageInfo = imageInfo;
                    }
                    break;

                    case ShaderResourceType.Sampler:
                    {
                        descriptorWrites[binding].descriptorType = VkDescriptorType.Sampler;
                        VkSamplerState         samplerState = cacheKey.SamplerStates[binding] ?? (VkSamplerState)_defaultSamplerState;
                        VkDescriptorImageInfo *imageInfo    = &imageInfos[binding];
                        imageInfo->sampler = samplerState.Sampler;
                        descriptorWrites[binding].pImageInfo = imageInfo;
                    }
                    break;

                    default:
                        throw Illegal.Value <ShaderResourceType>();
                    }
                }

                vkUpdateDescriptorSets(_device, (uint)resourceCount, ref descriptorWrites[0], 0, null);

                return(descriptorSet);
            }
        }