Vulkan入门

本人的显卡是GTX 770M,安装的驱动程序支持Vulkan.是否支持vulkan可以通过https://developer.nvidia.com/vulkan-driver查询结果



安装Vulkan SDK

下载并安装Vulkan SDK

https://vulkan.lunarg.com/sdk/home#windows

本人的安装目录是c:\VulkanSDK\1.0.39.1\


验证Vulkan SDK是否安装成功

cd bin

vulkaninfo


看到以上信息说明安装成功, 就可以进入开发了。


安装python3, cmake, git, vs2015, 安装过程省略, 相关可执行程序路径加入环境变量PATH



在sample目录执行build_windows_samples.bat生成visual studio的工程文件


用visual studio打开工程文件


完整的源代码如下

#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include "cube_data.h"


/* For this sample, we'll start with GLSL so the shader function is plain */
/* and then use the glslang GLSLtoSPV utility to convert it to SPIR-V for */
/* the driver.  We do this for clarity rather than using pre-compiled     */
/* SPIR-V                                                                 */


static const char *vertShaderText =
    "#version 400\n"
    "#extension GL_ARB_separate_shader_objects : enable\n"
    "#extension GL_ARB_shading_language_420pack : enable\n"
    "layout (std140, binding = 0) uniform bufferVals {\n"
    "    mat4 mvp;\n"
    "} myBufferVals;\n"
    "layout (location = 0) in vec4 pos;\n"
    "layout (location = 1) in vec4 inColor;\n"
    "layout (location = 0) out vec4 outColor;\n"
    "out gl_PerVertex { \n"
    "    vec4 gl_Position;\n"
    "};\n"
    "void main() {\n"
    "   outColor = inColor;\n"
    "   gl_Position = myBufferVals.mvp * pos;\n"
    "}\n";


static const char *fragShaderText =
    "#version 400\n"
    "#extension GL_ARB_separate_shader_objects : enable\n"
    "#extension GL_ARB_shading_language_420pack : enable\n"
    "layout (location = 0) in vec4 color;\n"
    "layout (location = 0) out vec4 outColor;\n"
    "void main() {\n"
    "   outColor = color;\n"
    "}\n";


int sample_main(int argc, char *argv[]) {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "Draw Cube";
    const bool depthPresent = true;


    process_command_line_args(info, argc, argv);
    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);


    init_command_pool(info);
    init_command_buffer(info);
    execute_begin_command_buffer(info);
    init_device_queue(info);
    init_swap_chain(info);
    init_depth_buffer(info);
    init_uniform_buffer(info);
    init_descriptor_and_pipeline_layouts(info, false);
    init_renderpass(info, depthPresent);
    init_shaders(info, vertShaderText, fragShaderText);
    init_framebuffers(info, depthPresent);
    init_vertex_buffer(info, g_vb_solid_face_colors_Data,
                       sizeof(g_vb_solid_face_colors_Data),
                       sizeof(g_vb_solid_face_colors_Data[0]), false);
    init_descriptor_pool(info, false);
    init_descriptor_set(info, false);
    init_pipeline_cache(info);
    init_pipeline(info, depthPresent);


    /* VULKAN_KEY_START */


    VkClearValue clear_values[2];
    clear_values[0].color.float32[0] = 0.2f;
    clear_values[0].color.float32[1] = 0.2f;
    clear_values[0].color.float32[2] = 0.2f;
    clear_values[0].color.float32[3] = 0.2f;
    clear_values[1].depthStencil.depth = 1.0f;
    clear_values[1].depthStencil.stencil = 0;


    VkSemaphore imageAcquiredSemaphore;
    VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
    imageAcquiredSemaphoreCreateInfo.sType =
        VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    imageAcquiredSemaphoreCreateInfo.pNext = NULL;
    imageAcquiredSemaphoreCreateInfo.flags = 0;


    res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo,
                            NULL, &imageAcquiredSemaphore);
    assert(res == VK_SUCCESS);


    // Get the index of the next available swapchain image:
    res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX,
                                imageAcquiredSemaphore, VK_NULL_HANDLE,
                                &info.current_buffer);
    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
    // return codes
    assert(res == VK_SUCCESS);


    VkRenderPassBeginInfo rp_begin;
    rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rp_begin.pNext = NULL;
    rp_begin.renderPass = info.render_pass;
    rp_begin.framebuffer = info.framebuffers[info.current_buffer];
    rp_begin.renderArea.offset.x = 0;
    rp_begin.renderArea.offset.y = 0;
    rp_begin.renderArea.extent.width = info.width;
    rp_begin.renderArea.extent.height = info.height;
    rp_begin.clearValueCount = 2;
    rp_begin.pClearValues = clear_values;


    vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);


    vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
    vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
                            info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS,
                            info.desc_set.data(), 0, NULL);


    const VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);


    init_viewports(info);
    init_scissors(info);


    vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0);
    vkCmdEndRenderPass(info.cmd);
    res = vkEndCommandBuffer(info.cmd);
    const VkCommandBuffer cmd_bufs[] = {info.cmd};
    VkFenceCreateInfo fenceInfo;
    VkFence drawFence;
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.pNext = NULL;
    fenceInfo.flags = 0;
    vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);


    VkPipelineStageFlags pipe_stage_flags =
        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submit_info[1] = {};
    submit_info[0].pNext = NULL;
    submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info[0].waitSemaphoreCount = 1;
    submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;
    submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
    submit_info[0].commandBufferCount = 1;
    submit_info[0].pCommandBuffers = cmd_bufs;
    submit_info[0].signalSemaphoreCount = 0;
    submit_info[0].pSignalSemaphores = NULL;


    /* Queue the command buffer for execution */
    res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence);
    assert(res == VK_SUCCESS);


    /* Now present the image in the window */


    VkPresentInfoKHR present;
    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present.pNext = NULL;
    present.swapchainCount = 1;
    present.pSwapchains = &info.swap_chain;
    present.pImageIndices = &info.current_buffer;
    present.pWaitSemaphores = NULL;
    present.waitSemaphoreCount = 0;
    present.pResults = NULL;


    /* Make sure command buffer is finished before presenting */
    do {
        res =
            vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
    } while (res == VK_TIMEOUT);


    assert(res == VK_SUCCESS);
    res = vkQueuePresentKHR(info.present_queue, &present);
    assert(res == VK_SUCCESS);


    wait_seconds(1);
    /* VULKAN_KEY_END */
    if (info.save_images)
        write_ppm(info, "drawcube");


    vkDestroySemaphore(info.device, imageAcquiredSemaphore, NULL);
    vkDestroyFence(info.device, drawFence, NULL);
    destroy_pipeline(info);
    destroy_pipeline_cache(info);
    destroy_descriptor_pool(info);
    destroy_vertex_buffer(info);
    destroy_framebuffers(info);
    destroy_shaders(info);
    destroy_renderpass(info);
    destroy_descriptor_and_pipeline_layouts(info);
    destroy_uniform_buffer(info);
    destroy_depth_buffer(info);
    destroy_swap_chain(info);
    destroy_command_buffer(info);
    destroy_command_pool(info);
    destroy_device(info);
    destroy_window(info);
    destroy_instance(info);
    return 0;
}


执行程序,最终效果如下



其它资料

https://developer.nvidia.com/Vulkan

https://developer.nvidia.com/vulkan-driver

https://vulkan-tutorial.com/

http://blog.csdn.net/lbknxy/article/category/6393151





  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vulkan被称为OpenGL的接班人,性能果然是霸气外漏,更能够承载下一个时代的图形渲染编程。 GPU高性能渲染的课题进入了一个新的阶段,对于计算细节的控制,多核CPU多线程渲染以及高性能算法的灵活设计需求日益旺盛。图形程序员需要有更加强力且灵活的工具,来“解锁”我们自身的控制能力,OpenGL的较高度封装性以及单纯的状态机模式显然已经无法适应现代化图形渲染的强烈需求。为什么要学习Vulkan?正如前言所说,Vulkan已经成为了下一个时代的图形渲染主流API,早已经被各大商业引擎(Unreal Engine、Unity3D)所支持。那么我们的同学就有如下问题需要明晰:1 作为游戏程序员我们只学会了UE或者Unity3D,那么就只能作为一个普通的程序员,如果能够结合Vulkan学习对商用引擎理解更加深刻,就可以更好的发挥引擎威力甚至更改引擎的源代码,实现更多的可能,让你在各大公司之间都“蛇形走位,游刃有余” 2 作为自研引擎工作人员,你可能在工业软件领域从业、也有可能在影视渲染领域从业、也可能在其他的图形系统领域(军工、GIS、BIM)等领域,那么熟练的掌握Vulkan就可以针对自己公司的不同领域需求进行不同的引擎定制开发,从而获得牢不可破的地位,对于自身职业发展有着极大的优势! 总而言之,越早学习Vulkan,就越能与别人拉开差距,让Vulkan称为你升职加薪、壮大不可替代性的核武器! 课程简介:本课程详细讲解了Vulkan从小白到入门的基础理论+实践知识,对于每一个知识点都会带领学员通过代码来实现功能。其中涵盖了计算机图形学基础理论,计算机图形学数学推导,Vulkan基础系统设计理论,基础单元(实例,设备,交换链), 渲染管线,RenderPass, 指令与多线程, 顶点描述与实验, Uniform与描述符, 图像与采样, 深度与反走样,模型与摄像机等内容;课程中会对Vulkan复杂抽象的API进行一次包装层的封装,将相关的API都进行聚合与接口设计,作为游戏或者图形引擎来讲,这是至关重要的第一步。这一个封装步骤,也被称为API-Wrapper,经过包装后的类库,同学可以在此之上根据自己的具体需求进行扩展,从而得到最适合自己的类库内容。本课程为系列化课程,在铸造基石篇章之后,会继续使用本包装类库进行改良,并且实现Vulkan API下的各类效果以及高级特性的开发教学。 课程优势:1 本课程会从计算机图形学的基础渲染管线原理出发,带领0基础的同学对计算机图形学进行快速认知,且对必要的知识点进行筛选提炼,去掉冗余繁杂的教学内容,更加适合新手对Vulkan渲染体系入门了解。 2 本课程会对计算机图形学所涉及的数学知识及如何应用到渲染当中,进行深入的讲解,带领同学对每一行公式展开认识,从三维世界如何映射到二维的屏幕,在学习完毕后会有清晰的知识体系 3 本课程会带领同学认知每一个Vulkan的API,并且在代码当中插入详细的注释,同学们在学习的时候就可以参照源代码进行一系列尝试以及学后复习 4 本课程所设计的包装层,会带领同学一行一行代码实现,现场进行Debug,对于Vulkan常出现的一些问题进行深入探讨与现场纠正  学习所得:1 同学们在学习后可以完全了解从三维世界的抽象物体,如何一步步渲染称为一个屏幕上的像素点。2 同学们在学习后可以完全掌握基础的Vulkan图形API,并且了解Vulkan当中繁多的对象之间相互的联系,从而可以设计更好的图形程序3 同学们在跟随课程进行代码编写后,可以获得一个轻量级的Vulkan底层API封装库(Wrapper),从而可以在此之上封装上层的应用,得到自己的迷你Vulkan图形渲染引擎当然,在达到如上三点之后,如果可以更进一步学习Vulkan的进阶课程,同学们可以获得更好的职业发展,升职加薪之路会更加清晰,成为公司不可替代的强力工程师 本课程含有全套源代码,同学购买后,可以在课程附件当中下载 完全不懂图形学可以学习么?使用层面上来讲是没有问题的,老师在每个api讲解的时候,都会仔细分析api背后的原理,所以可以跟随下来的话,能够编程与原理相融,学会使用 数学不好可以学习么?学习图形类课程,最好能够入门级别的线性代数,具体说就是: 1 向量操作 2 矩阵乘法 3 矩阵的逆、转置 这几个点就足够 学习后对就业面试有什么作用?目前类似Vulkan的渲染知识是一切引擎的基础,只要能够跟随每一节课写代码做下来,游戏公司、工业软件公司等都是非常容易进去的,因为原理层面已经通晓,面试就会特别有优势。同学可以在简历上写熟悉VulkanAPI并且有代码经验,对于建立筛选以及面试都会有很大的帮助,对于薪资也会有大幅度提升

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值