예제 #1
0
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapChain, uint32_t *pCount,
                                                                       VkImage *pImages) {
    layer_data *my_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
    VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
    VkResult result = my_data->pfnGetSwapchainImagesKHR(device, swapChain, pCount, pImages);
    VkResult U_ASSERT_ONLY err;

    /* GetSwapChainImagesWSI may be called without an images buffer, in which
     * case it
     * just returns the count to the caller. We're only interested in acting on
     * the
     * /actual/ fetch of the images.
     */
    if (pImages) {
        auto data = (*my_data->swapChains)[swapChain];

        for (uint32_t i = 0; i < *pCount; i++) {
            /* Create attachment view for each */
            VkImageViewCreateInfo ivci;
            ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
            ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
            ivci.pNext = nullptr;
            ivci.format = data->format;
            ivci.components.r = VK_COMPONENT_SWIZZLE_R;
            ivci.components.g = VK_COMPONENT_SWIZZLE_G;
            ivci.components.b = VK_COMPONENT_SWIZZLE_B;
            ivci.components.a = VK_COMPONENT_SWIZZLE_A;
            ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
            ivci.subresourceRange.baseMipLevel = 0;
            ivci.subresourceRange.levelCount = 1;
            ivci.subresourceRange.baseArrayLayer = 0;
            ivci.subresourceRange.layerCount = 1;
            ivci.image = pImages[i];
            ivci.flags = 0;

            VkImageView v;
            pTable->CreateImageView(device, &ivci, nullptr, &v);

            /* Create framebuffer for each */
            VkFramebufferCreateInfo fci;
            fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
            fci.pNext = nullptr;
            fci.flags = 0;
            fci.renderPass = data->render_pass;
            fci.attachmentCount = 1;
            fci.pAttachments = &v;
            fci.width = data->width;
            fci.height = data->height;
            fci.layers = 1;

            VkFramebuffer fb;
            pTable->CreateFramebuffer(device, &fci, nullptr, &fb);

            /* Create command buffer for each */
            VkCommandBufferAllocateInfo cbai;
            cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
            cbai.pNext = nullptr;
            cbai.commandPool = my_data->pool;
            cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
            cbai.commandBufferCount = 1;

            VkCommandBuffer cmd;
            pTable->AllocateCommandBuffers(device, &cbai, &cmd);

            /* We have just created a dispatchable object, but the dispatch
             * table has not been placed in the object yet.
             * When a "normal" application creates a command buffer,
             * the dispatch table is installed by the top-level binding
             * (trampoline.c).
             * But here, we have to do it ourselves. */

            if (!my_data->pfn_dev_init) {
                *((const void **)cmd) = *(void **)device;
            } else {
                err = my_data->pfn_dev_init(device, (void *)cmd);
                assert(!err);
            }

            /* Create vertex buffer */
            VkBufferCreateInfo bci;
            memset(&bci, 0, sizeof(bci));
            bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bci.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
            bci.size = sizeof(vertex) * MAX_TEXT_VERTICES;

            VkBuffer buf;
            err = pTable->CreateBuffer(device, &bci, nullptr, &buf);
            assert(!err);

            VkMemoryRequirements mem_reqs;
            pTable->GetBufferMemoryRequirements(device, buf, &mem_reqs);
            assert(!err);

            VkMemoryAllocateInfo mem_alloc;
            memset(&mem_alloc, 0, sizeof(mem_alloc));
            mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
            mem_alloc.allocationSize = mem_reqs.size;
            mem_alloc.memoryTypeIndex = choose_memory_type(
                my_data->gpu, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

            VkDeviceMemory mem;
            err = pTable->AllocateMemory(device, &mem_alloc, nullptr, &mem);
            assert(!err);

            err = pTable->BindBufferMemory(device, buf, mem, 0);
            assert(!err);

            auto imageData = new WsiImageData;
            imageData->image = pImages[i];
            imageData->view = v;
            imageData->framebuffer = fb;
            imageData->cmd = cmd;
            imageData->vertexBuffer = buf;
            imageData->vertexBufferMemory = mem;
            imageData->numVertices = 0;
            imageData->vertexBufferSize = mem_alloc.allocationSize;

            data->presentableImages.push_back(imageData);
        }
    }
    return result;
}
예제 #2
0
static void after_device_create(VkPhysicalDevice gpu, VkDevice device, layer_data *data) {
    VkResult U_ASSERT_ONLY err;

    data->gpu = gpu;
    data->dev = device;
    data->frame = 0;
    data->cmdBuffersThisFrame = 0;

    VkLayerDispatchTable *pTable = data->device_dispatch_table;

    /* Get our WSI hooks in. */
    data->pfnCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)pTable->GetDeviceProcAddr(device, "vkCreateSwapchainKHR");
    data->pfnGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)pTable->GetDeviceProcAddr(device, "vkGetSwapchainImagesKHR");
    data->pfnQueuePresentKHR = (PFN_vkQueuePresentKHR)pTable->GetDeviceProcAddr(device, "vkQueuePresentKHR");
    data->pfnDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)pTable->GetDeviceProcAddr(device, "vkDestroySwapchainKHR");
    data->swapChains = new std::unordered_map<VkSwapchainKHR, SwapChainData *>;

    /* Command pool */
    VkCommandPoolCreateInfo cpci;
    cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    cpci.pNext = nullptr;
    cpci.queueFamilyIndex = data->graphicsQueueFamilyIndex;
    cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    err = pTable->CreateCommandPool(device, &cpci, nullptr, &data->pool);
    assert(!err);

    /* Create the objects we need */

    /* Compile the shaders */
    compile_shader(device, VULKAN_SAMPLES_BASE_DIR "/Layer-Samples/data/overlay-vert.spv", &data->vsShaderModule);
    compile_shader(device, VULKAN_SAMPLES_BASE_DIR "/Layer-Samples/data/overlay-frag.spv", &data->fsShaderModule);

    /* Upload the font bitmap */
    VkImageCreateInfo ici;
    memset(&ici, 0, sizeof(ici));
    ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    ici.imageType = VK_IMAGE_TYPE_2D;
    ici.format = VK_FORMAT_R8_UNORM;
    ici.extent.width = FONT_ATLAS_SIZE;
    ici.extent.height = FONT_ATLAS_SIZE;
    ici.extent.depth = 1;
    ici.mipLevels = 1;
    ici.arrayLayers = 1;
    ici.samples = VK_SAMPLE_COUNT_1_BIT;
    ici.tiling = VK_IMAGE_TILING_LINEAR;
    ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
    ici.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;

    err = pTable->CreateImage(device, &ici, nullptr, &data->fontGlyphsImage);
    assert(!err);

    VkMemoryRequirements mem_reqs;
    pTable->GetImageMemoryRequirements(device, data->fontGlyphsImage, &mem_reqs);

    VkMemoryAllocateInfo mem_alloc;
    memset(&mem_alloc, 0, sizeof(mem_alloc));
    mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    mem_alloc.allocationSize = mem_reqs.size;
    mem_alloc.memoryTypeIndex = choose_memory_type(gpu, mem_reqs.memoryTypeBits,
                                                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

    err = pTable->AllocateMemory(device, &mem_alloc, nullptr, &data->fontGlyphsMemory);
    assert(!err);
    err = pTable->BindImageMemory(device, data->fontGlyphsImage, data->fontGlyphsMemory, 0);
    assert(!err);

    VkImageSubresource subres;
    subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    subres.mipLevel = 0;
    subres.arrayLayer = 0;
    VkSubresourceLayout layout;
    void *bits;

    pTable->GetImageSubresourceLayout(device, data->fontGlyphsImage, &subres, &layout);

    /* ensure we can directly upload into this layout */
    assert(!layout.offset);
    assert(layout.size >= FONT_ATLAS_SIZE * FONT_ATLAS_SIZE);
    assert(layout.rowPitch == FONT_ATLAS_SIZE);

    err = pTable->MapMemory(device, data->fontGlyphsMemory, 0, VK_WHOLE_SIZE, 0, &bits);
    assert(!err);

    /* Load the font glyphs directly into the mapped buffer */
    std::vector<unsigned char> fontData;
    get_file_contents(VULKAN_SAMPLES_BASE_DIR "/Layer-Samples/data/FreeSans.ttf", fontData);
    stbtt_BakeFontBitmap(&fontData[0], 0, FONT_SIZE_PIXELS, (unsigned char *)bits, FONT_ATLAS_SIZE, FONT_ATLAS_SIZE, 32, 96,
                         data->glyphs);

    pTable->UnmapMemory(device, data->fontGlyphsMemory);

    VkImageViewCreateInfo ivci;
    ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
    ivci.pNext = nullptr;
    ivci.format = ici.format;
    ivci.components.r = VK_COMPONENT_SWIZZLE_R;
    ivci.components.g = VK_COMPONENT_SWIZZLE_G;
    ivci.components.b = VK_COMPONENT_SWIZZLE_B;
    ivci.components.a = VK_COMPONENT_SWIZZLE_A;
    ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    ivci.subresourceRange.baseMipLevel = 0;
    ivci.subresourceRange.levelCount = 1;
    ivci.subresourceRange.baseArrayLayer = 0;
    ivci.subresourceRange.layerCount = 1;
    ivci.image = data->fontGlyphsImage;
    ivci.flags = 0;

    err = pTable->CreateImageView(device, &ivci, nullptr, &data->fontGlyphsImageView);
    assert(!err);

    /* transition from undefined layout to shader readonly so we can use it.
     * requires a command buffer. */
    VkCommandBufferAllocateInfo cbai;
    cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    cbai.pNext = nullptr;
    cbai.commandPool = data->pool;
    cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    cbai.commandBufferCount = 1;

    VkCommandBuffer cmd;
    err = pTable->AllocateCommandBuffers(device, &cbai, &cmd);
    assert(!err);

    /* We have just created a dispatchable object, but the dispatch table has
     * not been placed in the object yet.
     * When a "normal" application creates a command buffer,
     * the dispatch table is installed by the top-level binding (trampoline.c).
     * But here, we have to do it ourselves. */
    if (!data->pfn_dev_init) {
        *((const void **)cmd) = *(void **)device;
    } else {
        err = data->pfn_dev_init(device, (void *)cmd);
        assert(!err);
    }

    VkCommandBufferBeginInfo cbbi;
    cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    cbbi.pNext = nullptr;
    cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    cbbi.pInheritanceInfo = nullptr;

    err = pTable->BeginCommandBuffer(cmd, &cbbi);
    assert(!err);

    VkImageMemoryBarrier imb;
    imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    imb.pNext = nullptr;
    imb.dstAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
    imb.srcAccessMask = 0;
    imb.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    imb.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    imb.image = data->fontGlyphsImage;
    imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    imb.subresourceRange.baseMipLevel = 0;
    imb.subresourceRange.levelCount = 1;
    imb.subresourceRange.baseArrayLayer = 0;
    imb.subresourceRange.layerCount = 1;
    imb.srcQueueFamilyIndex = data->graphicsQueueFamilyIndex;
    imb.dstQueueFamilyIndex = data->graphicsQueueFamilyIndex;

    pTable->CmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0 /* dependency flags */,
                               0, nullptr, /* memory barriers */
                               0, nullptr, /* buffer memory barriers */
                               1, &imb);   /* image memory barriers */

    pTable->EndCommandBuffer(cmd);
    data->fontUploadCmdBuffer = cmd;
    data->fontUploadComplete = false; /* we will schedule this at first present on this device */

#ifdef OVERLAY_DEBUG
    printf("Font upload done.\n");
#endif

    /* create a sampler to use with the texture */
    VkSamplerCreateInfo sci;
    sci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
    sci.pNext = nullptr;
    sci.flags = 0;
    sci.magFilter = VK_FILTER_NEAREST;
    sci.minFilter = VK_FILTER_NEAREST;
    sci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
    sci.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
    sci.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
    sci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
    sci.mipLodBias = 0.0f;
    sci.anisotropyEnable = false;
    sci.maxAnisotropy = 1;
    sci.compareEnable = false;
    sci.compareOp = VK_COMPARE_OP_NEVER;
    sci.minLod = 0.0f;
    sci.maxLod = 0.0f;
    sci.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
    sci.unnormalizedCoordinates = VK_FALSE;

    err = pTable->CreateSampler(device, &sci, nullptr, &data->sampler);
    assert(!err);

    /* descriptor set stuff so we can use the texture from a shader. */
    VkDescriptorSetLayoutBinding dslb[1];
    dslb[0].binding = 0;
    dslb[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    dslb[0].descriptorCount = 1;
    dslb[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
    dslb[0].pImmutableSamplers = nullptr;

    VkDescriptorSetLayoutCreateInfo dslci;
    memset(&dslci, 0, sizeof(dslci));
    dslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    dslci.pNext = nullptr;
    dslci.bindingCount = 1;
    dslci.pBindings = dslb;

    err = pTable->CreateDescriptorSetLayout(device, &dslci, nullptr, &data->dsl);
    assert(!err);

    VkPipelineLayoutCreateInfo plci;
    memset(&plci, 0, sizeof(plci));
    plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    plci.setLayoutCount = 1;
    plci.pSetLayouts = &data->dsl;

    err = pTable->CreatePipelineLayout(device, &plci, nullptr, &data->pl);
    assert(!err);

    VkDescriptorPoolSize dtc[1];
    dtc[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    dtc[0].descriptorCount = 1;
    VkDescriptorPoolCreateInfo dpci;
    dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    dpci.pNext = nullptr;
    dpci.flags = 0;
    dpci.maxSets = 1;
    dpci.poolSizeCount = 1;
    dpci.pPoolSizes = dtc;

    err = pTable->CreateDescriptorPool(device, &dpci, nullptr, &data->desc_pool);
    assert(!err);

    VkDescriptorSetAllocateInfo dsai;
    dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    dsai.pNext = nullptr;
    dsai.descriptorPool = data->desc_pool;
    dsai.descriptorSetCount = 1;
    dsai.pSetLayouts = &data->dsl;
    err = pTable->AllocateDescriptorSets(device, &dsai, &data->desc_set);
    assert(!err);

    VkDescriptorImageInfo descs[1];
    descs[0].sampler = data->sampler;
    descs[0].imageView = data->fontGlyphsImageView;
    descs[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;  // TODO: cube does this, is it correct?

    VkWriteDescriptorSet writes[1];
    memset(&writes, 0, sizeof(writes));
    writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    writes[0].dstSet = data->desc_set;
    writes[0].dstBinding = 0;
    writes[0].descriptorCount = 1;
    writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    writes[0].pImageInfo = descs;

    pTable->UpdateDescriptorSets(device, 1, writes, 0, nullptr);

    VkFenceCreateInfo fci;
    fci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fci.pNext = NULL;
    fci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
    pTable->CreateFence(device, &fci, NULL, &data->fence);
}