Skip to content

Instantly share code, notes, and snippets.

@KunstDerFuge
Created June 5, 2023 01:03
Show Gist options
  • Save KunstDerFuge/2622af90d659c6f35830fb4da0d7e927 to your computer and use it in GitHub Desktop.
Save KunstDerFuge/2622af90d659c6f35830fb4da0d7e927 to your computer and use it in GitHub Desktop.
################################
#
# INSTALL PREREQUISITE PACKAGES:
# pip install PySDL2 vulkan
#
# Based on script from https://github.com/realitix/vulkan/blob/master/example/example_sdl2.py
import ctypes
import os
import sdl2
import sdl2.ext
import time
from vulkan import *
WIDTH = 400
HEIGHT = 400
# ----------
# Init sdl2
if sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) != 0:
raise Exception(sdl2.SDL_GetError())
window = sdl2.SDL_CreateWindow(
'test'.encode('ascii'),
sdl2.SDL_WINDOWPOS_UNDEFINED,
sdl2.SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, 0)
if not window:
raise Exception(sdl2.SDL_GetError())
wm_info = sdl2.SDL_SysWMinfo()
sdl2.SDL_VERSION(wm_info.version)
sdl2.SDL_GetWindowWMInfo(window, ctypes.byref(wm_info))
# ----------
# Create instance
appInfo = VkApplicationInfo(
sType=VK_STRUCTURE_TYPE_APPLICATION_INFO,
pApplicationName="Hello Triangle",
applicationVersion=VK_MAKE_VERSION(1, 0, 0),
pEngineName="No Engine",
engineVersion=VK_MAKE_VERSION(1, 0, 0),
apiVersion=VK_API_VERSION_1_0)
extensions = vkEnumerateInstanceExtensionProperties(None)
extensions = [e.extensionName for e in extensions]
print(f"\navailable instance extensions: {' '.join(extensions)}\n")
layers = vkEnumerateInstanceLayerProperties()
layers = [l.layerName for l in layers]
print("available layers: %s\n" % layers)
if 'VK_LAYER_KHRONOS_validation' in layers:
layers = ['VK_LAYER_KHRONOS_validation']
elif 'VK_LAYER_LUNARG_standard_validation' in layers:
layers = ['VK_LAYER_LUNARG_standard_validation']
else:
layers = []
extensions = ['VK_KHR_surface', 'VK_EXT_debug_report']
if wm_info.subsystem == sdl2.SDL_SYSWM_WINDOWS:
extensions.append('VK_KHR_win32_surface')
elif wm_info.subsystem == sdl2.SDL_SYSWM_X11:
extensions.append('VK_KHR_xlib_surface')
elif wm_info.subsystem == sdl2.SDL_SYSWM_WAYLAND:
extensions.append('VK_KHR_wayland_surface')
else:
raise Exception("Platform not supported")
createInfo = VkInstanceCreateInfo(
sType=VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
flags=0,
pApplicationInfo=appInfo,
enabledExtensionCount=len(extensions),
ppEnabledExtensionNames=extensions,
enabledLayerCount=len(layers),
ppEnabledLayerNames=layers)
instance = vkCreateInstance(createInfo, None)
# ----------
# Debug instance
vkCreateDebugReportCallbackEXT = vkGetInstanceProcAddr(
instance,
"vkCreateDebugReportCallbackEXT")
vkDestroyDebugReportCallbackEXT = vkGetInstanceProcAddr(
instance,
"vkDestroyDebugReportCallbackEXT")
def debugCallback(*args):
print('DEBUG: ' + args[5] + ' ' + args[6])
return 0
debug_create = VkDebugReportCallbackCreateInfoEXT(
sType=VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
flags=VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
pfnCallback=debugCallback)
callback = vkCreateDebugReportCallbackEXT(instance, debug_create, None)
# ----------
# Create surface
vkDestroySurfaceKHR = vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR")
def surface_xlib():
print("Create Xlib surface")
vkCreateXlibSurfaceKHR = vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR")
surface_create = VkXlibSurfaceCreateInfoKHR(
sType=VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
dpy=wm_info.info.x11.display,
window=wm_info.info.x11.window,
flags=0)
return vkCreateXlibSurfaceKHR(instance, surface_create, None)
def surface_wayland():
print("Create wayland surface")
vkCreateWaylandSurfaceKHR = vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR")
surface_create = VkWaylandSurfaceCreateInfoKHR(
sType=VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
display=wm_info.info.wl.display,
surface=wm_info.info.wl.surface,
flags=0)
return vkCreateWaylandSurfaceKHR(instance, surface_create, None)
def surface_win32():
def get_instance(hWnd):
"""Hack needed before SDL 2.0.6"""
from cffi import FFI
_ffi = FFI()
_ffi.cdef('long __stdcall GetWindowLongA(void* hWnd, int nIndex);')
_lib = _ffi.dlopen('User32.dll')
return _lib.GetWindowLongA(_ffi.cast('void*', hWnd), -6)
print("Create windows surface")
vkCreateWin32SurfaceKHR = vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR")
surface_create = VkWin32SurfaceCreateInfoKHR(
sType=VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
hinstance=get_instance(wm_info.info.win.window),
hwnd=wm_info.info.win.window,
flags=0)
return vkCreateWin32SurfaceKHR(instance, surface_create, None)
surface_mapping = {
sdl2.SDL_SYSWM_X11: surface_xlib,
sdl2.SDL_SYSWM_WAYLAND: surface_wayland,
sdl2.SDL_SYSWM_WINDOWS: surface_win32
}
surface = surface_mapping[wm_info.subsystem]()
# ----------
# Select physical device
physical_devices = vkEnumeratePhysicalDevices(instance)
physical_devices_features = {physical_device: vkGetPhysicalDeviceFeatures(physical_device)
for physical_device in physical_devices}
physical_devices_properties = {physical_device: vkGetPhysicalDeviceProperties(physical_device)
for physical_device in physical_devices}
physical_device = physical_devices[0]
print("availables devices: %s" % [p.deviceName
for p in physical_devices_properties.values()])
print("selected device: %s\n" % physical_devices_properties[physical_device].deviceName)
# ----------
# Select queue family
vkGetPhysicalDeviceSurfaceSupportKHR = vkGetInstanceProcAddr(
instance, 'vkGetPhysicalDeviceSurfaceSupportKHR')
queue_families = vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice=physical_device)
print("%s available queue family" % len(queue_families))
queue_family_graphic_index = -1
queue_family_present_index = -1
for i, queue_family in enumerate(queue_families):
# Currently, we set present index like graphic index
support_present = vkGetPhysicalDeviceSurfaceSupportKHR(
physicalDevice=physical_device,
queueFamilyIndex=i,
surface=surface)
if (queue_family.queueCount > 0 and
queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT):
queue_family_graphic_index = i
queue_family_present_index = i
# if queue_family.queueCount > 0 and support_present:
# queue_family_present_index = i
print("indice of selected queue families, graphic: %s, presentation: %s\n" % (
queue_family_graphic_index, queue_family_present_index))
# ----------
# Create logical device and queues
extensions = vkEnumerateDeviceExtensionProperties(physicalDevice=physical_device, pLayerName=None)
extensions = [e.extensionName for e in extensions]
print(f"\navailable device extensions: {' '.join(extensions)}\n")
#only use the extensions necessary
extensions = [VK_KHR_SWAPCHAIN_EXTENSION_NAME]
queues_create = [VkDeviceQueueCreateInfo(sType=VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
queueFamilyIndex=i,
queueCount=1,
pQueuePriorities=[1],
flags=0)
for i in {queue_family_graphic_index,
queue_family_present_index}]
device_create = VkDeviceCreateInfo(
sType=VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
pQueueCreateInfos=queues_create,
queueCreateInfoCount=len(queues_create),
pEnabledFeatures=physical_devices_features[physical_device],
flags=0,
enabledLayerCount=len(layers),
ppEnabledLayerNames=layers,
enabledExtensionCount=len(extensions),
ppEnabledExtensionNames=extensions
)
logical_device = vkCreateDevice(physical_device, device_create, None)
graphic_queue = vkGetDeviceQueue(
device=logical_device,
queueFamilyIndex=queue_family_graphic_index,
queueIndex=0)
presentation_queue = vkGetDeviceQueue(
device=logical_device,
queueFamilyIndex=queue_family_present_index,
queueIndex=0)
print("Logical device and graphic queue successfully created\n")
# ----------
# Create swapchain
vkGetPhysicalDeviceSurfaceCapabilitiesKHR = vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")
vkGetPhysicalDeviceSurfaceFormatsKHR = vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR")
vkGetPhysicalDeviceSurfacePresentModesKHR = vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR")
surface_capabilities = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice=physical_device, surface=surface)
surface_formats = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice=physical_device, surface=surface)
surface_present_modes = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice=physical_device, surface=surface)
if not surface_formats or not surface_present_modes:
raise Exception('No available swapchain')
def get_surface_format(formats):
for f in formats:
if f.format == VK_FORMAT_UNDEFINED:
return f
if (f.format == VK_FORMAT_B8G8R8A8_UNORM and
f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR):
return f
return formats[0]
def get_surface_present_mode(present_modes):
for p in present_modes:
if p == VK_PRESENT_MODE_MAILBOX_KHR:
return p
return VK_PRESENT_MODE_FIFO_KHR;
def get_swap_extent(capabilities):
uint32_max = 4294967295
if capabilities.currentExtent.width != uint32_max:
return VkExtent2D(width=capabilities.currentExtent.width,
height=capabilities.currentExtent.height)
width = max(
capabilities.minImageExtent.width,
min(capabilities.maxImageExtent.width, WIDTH))
height = max(
capabilities.minImageExtent.height,
min(capabilities.maxImageExtent.height, HEIGHT))
actualExtent = VkExtent2D(width=width, height=height);
return actualExtent
surface_format = get_surface_format(surface_formats)
present_mode = get_surface_present_mode(surface_present_modes)
extent = get_swap_extent(surface_capabilities)
imageCount = surface_capabilities.minImageCount + 1;
if surface_capabilities.maxImageCount > 0 and imageCount > surface_capabilities.maxImageCount:
imageCount = surface_capabilities.maxImageCount
print('selected format: %s' % surface_format.format)
print('%s available swapchain present modes' % len(surface_present_modes))
imageSharingMode = VK_SHARING_MODE_EXCLUSIVE
queueFamilyIndexCount = 0
pQueueFamilyIndices = None
if queue_family_graphic_index != queue_family_present_index:
imageSharingMode = VK_SHARING_MODE_CONCURRENT
queueFamilyIndexCount = 2
pQueueFamilyIndices = [queue_family_graphic_index, queue_family_present_index]
vkCreateSwapchainKHR = vkGetInstanceProcAddr(instance, 'vkCreateSwapchainKHR')
vkDestroySwapchainKHR = vkGetInstanceProcAddr(instance, 'vkDestroySwapchainKHR')
vkGetSwapchainImagesKHR = vkGetInstanceProcAddr(instance, 'vkGetSwapchainImagesKHR')
swapchain_create = VkSwapchainCreateInfoKHR(
sType=VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
flags=0,
surface=surface,
minImageCount=imageCount,
imageFormat=surface_format.format,
imageColorSpace=surface_format.colorSpace,
imageExtent=extent,
imageArrayLayers=1,
imageUsage=VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
imageSharingMode=imageSharingMode,
queueFamilyIndexCount=queueFamilyIndexCount,
pQueueFamilyIndices=pQueueFamilyIndices,
compositeAlpha=VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
presentMode=present_mode,
clipped=VK_TRUE,
oldSwapchain=None,
preTransform=surface_capabilities.currentTransform)
swapchain = vkCreateSwapchainKHR(logical_device, swapchain_create, None)
swapchain_images = vkGetSwapchainImagesKHR(logical_device, swapchain)
# Create image view for each image in swapchain
image_views = []
for image in swapchain_images:
subresourceRange = VkImageSubresourceRange(
aspectMask=VK_IMAGE_ASPECT_COLOR_BIT,
baseMipLevel=0,
levelCount=1,
baseArrayLayer=0,
layerCount=1)
components = VkComponentMapping(
r=VK_COMPONENT_SWIZZLE_IDENTITY,
g=VK_COMPONENT_SWIZZLE_IDENTITY,
b=VK_COMPONENT_SWIZZLE_IDENTITY,
a=VK_COMPONENT_SWIZZLE_IDENTITY)
imageview_create = VkImageViewCreateInfo(
sType=VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
image=image,
flags=0,
viewType=VK_IMAGE_VIEW_TYPE_2D,
format=surface_format.format,
components=components,
subresourceRange=subresourceRange)
image_views.append(vkCreateImageView(logical_device, imageview_create, None))
print("%s images view created" % len(image_views))
# Load spirv shader
path = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(path, "vert.spv"), 'rb') as f:
vert_shader_spirv = f.read()
with open(os.path.join(path, "frag.spv"), 'rb') as f:
frag_shader_spirv = f.read()
# Create shader
vert_shader_create = VkShaderModuleCreateInfo(
sType=VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
flags=0,
codeSize=len(vert_shader_spirv),
pCode=vert_shader_spirv
)
vert_shader_module = vkCreateShaderModule(logical_device, vert_shader_create, None)
frag_shader_create = VkShaderModuleCreateInfo(
sType=VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
flags=0,
codeSize=len(frag_shader_spirv),
pCode=frag_shader_spirv)
frag_shader_module = vkCreateShaderModule(logical_device, frag_shader_create, None)
# Create shader stage
vert_stage_create = VkPipelineShaderStageCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
stage=VK_SHADER_STAGE_VERTEX_BIT,
module=vert_shader_module,
flags=0,
pSpecializationInfo=None,
pName='main')
frag_stage_create = VkPipelineShaderStageCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
stage=VK_SHADER_STAGE_FRAGMENT_BIT,
module=frag_shader_module,
flags=0,
pSpecializationInfo=None,
pName='main')
# Create render pass
color_attachement = VkAttachmentDescription(
flags=0,
format=surface_format.format,
samples=VK_SAMPLE_COUNT_1_BIT,
loadOp=VK_ATTACHMENT_LOAD_OP_CLEAR,
storeOp=VK_ATTACHMENT_STORE_OP_STORE,
stencilLoadOp=VK_ATTACHMENT_LOAD_OP_DONT_CARE,
stencilStoreOp=VK_ATTACHMENT_STORE_OP_DONT_CARE,
initialLayout=VK_IMAGE_LAYOUT_UNDEFINED,
finalLayout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
color_attachement_reference = VkAttachmentReference(
attachment=0,
layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
sub_pass = VkSubpassDescription(
flags=0,
pipelineBindPoint=VK_PIPELINE_BIND_POINT_GRAPHICS,
inputAttachmentCount=0,
pInputAttachments=None,
pResolveAttachments=None,
pDepthStencilAttachment=None,
preserveAttachmentCount=0,
pPreserveAttachments=None,
colorAttachmentCount=1,
pColorAttachments=[color_attachement_reference])
dependency = VkSubpassDependency(
dependencyFlags=0,
srcSubpass=VK_SUBPASS_EXTERNAL,
dstSubpass=0,
srcStageMask=VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
srcAccessMask=0,
dstStageMask=VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
dstAccessMask=VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
render_pass_create = VkRenderPassCreateInfo(
flags=0,
sType=VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
attachmentCount=1,
pAttachments=[color_attachement],
subpassCount=1,
pSubpasses=[sub_pass],
dependencyCount=1,
pDependencies=[dependency])
render_pass = vkCreateRenderPass(logical_device, render_pass_create, None)
# Create graphic pipeline
vertex_input_create = VkPipelineVertexInputStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
flags=0,
vertexBindingDescriptionCount=0,
pVertexBindingDescriptions=None,
vertexAttributeDescriptionCount=0,
pVertexAttributeDescriptions=None)
input_assembly_create = VkPipelineInputAssemblyStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
flags=0,
topology=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
primitiveRestartEnable=VK_FALSE)
viewport = VkViewport(
x=0., y=0., width=float(extent.width), height=float(extent.height),
minDepth=0., maxDepth=1.)
scissor_offset = VkOffset2D(x=0, y=0)
scissor = VkRect2D(offset=scissor_offset, extent=extent)
viewport_state_create = VkPipelineViewportStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
flags=0,
viewportCount=1,
pViewports=[viewport],
scissorCount=1,
pScissors=[scissor])
rasterizer_create = VkPipelineRasterizationStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
flags=0,
depthClampEnable=VK_FALSE,
rasterizerDiscardEnable=VK_FALSE,
polygonMode=VK_POLYGON_MODE_FILL,
lineWidth=1,
cullMode=VK_CULL_MODE_BACK_BIT,
frontFace=VK_FRONT_FACE_CLOCKWISE,
depthBiasEnable=VK_FALSE,
depthBiasConstantFactor=0.,
depthBiasClamp=0.,
depthBiasSlopeFactor=0.)
multisample_create = VkPipelineMultisampleStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
flags=0,
sampleShadingEnable=VK_FALSE,
rasterizationSamples=VK_SAMPLE_COUNT_1_BIT,
minSampleShading=1,
pSampleMask=None,
alphaToCoverageEnable=VK_FALSE,
alphaToOneEnable=VK_FALSE)
color_blend_attachement = VkPipelineColorBlendAttachmentState(
colorWriteMask=VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
blendEnable=VK_FALSE,
srcColorBlendFactor=VK_BLEND_FACTOR_ONE,
dstColorBlendFactor=VK_BLEND_FACTOR_ZERO,
colorBlendOp=VK_BLEND_OP_ADD,
srcAlphaBlendFactor=VK_BLEND_FACTOR_ONE,
dstAlphaBlendFactor=VK_BLEND_FACTOR_ZERO,
alphaBlendOp=VK_BLEND_OP_ADD)
color_blend_create = VkPipelineColorBlendStateCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
flags=0,
logicOpEnable=VK_FALSE,
logicOp=VK_LOGIC_OP_COPY,
attachmentCount=1,
pAttachments=[color_blend_attachement],
blendConstants=[0, 0, 0, 0])
push_constant_ranges = VkPushConstantRange(
stageFlags=0,
offset=0,
size=0)
pipeline_layout_create = VkPipelineLayoutCreateInfo(
sType=VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
flags=0,
setLayoutCount=0,
pSetLayouts=None,
pushConstantRangeCount=0,
pPushConstantRanges=[push_constant_ranges])
pipeline_layout = vkCreatePipelineLayout(logical_device, pipeline_layout_create, None)
# Finally create graphic pipeline
pipeline_create = VkGraphicsPipelineCreateInfo(
sType=VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
flags=0,
stageCount=2,
pStages=[vert_stage_create, frag_stage_create],
pVertexInputState=vertex_input_create,
pInputAssemblyState=input_assembly_create,
pTessellationState=None,
pViewportState=viewport_state_create,
pRasterizationState=rasterizer_create,
pMultisampleState=multisample_create,
pDepthStencilState=None,
pColorBlendState=color_blend_create,
pDynamicState=None,
layout=pipeline_layout,
renderPass=render_pass,
subpass=0,
basePipelineHandle=None,
basePipelineIndex=-1)
pipelines = vkCreateGraphicsPipelines(logical_device, None, 1, [pipeline_create], None)
pipeline = pipelines[0]
# Framebuffers creation
framebuffers = []
for image in image_views:
attachments = [image]
framebuffer_create = VkFramebufferCreateInfo(
sType=VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
flags=0,
renderPass=render_pass,
attachmentCount=len(attachments),
pAttachments=attachments,
width=extent.width,
height=extent.height,
layers=1)
framebuffers.append(
vkCreateFramebuffer(logical_device, framebuffer_create, None))
# Create command pools
command_pool_create = VkCommandPoolCreateInfo(
sType=VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
queueFamilyIndex=queue_family_graphic_index,
flags=0)
command_pool = vkCreateCommandPool(logical_device, command_pool_create, None)
# Create command buffers
command_buffers_create = VkCommandBufferAllocateInfo(
sType=VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
commandPool=command_pool,
level=VK_COMMAND_BUFFER_LEVEL_PRIMARY,
commandBufferCount=len(framebuffers))
command_buffers = vkAllocateCommandBuffers(logical_device, command_buffers_create)
# Record command buffer
for i, command_buffer in enumerate(command_buffers):
command_buffer_begin_create = VkCommandBufferBeginInfo(
sType=VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
flags=VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
pInheritanceInfo=None)
vkBeginCommandBuffer(command_buffer, command_buffer_begin_create)
# Create render pass
render_area = VkRect2D(offset=VkOffset2D(x=0, y=0),
extent=extent)
color = VkClearColorValue(float32=[0, 1, 0, 1])
clear_value = VkClearValue(color=color)
render_pass_begin_create = VkRenderPassBeginInfo(
sType=VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
renderPass=render_pass,
framebuffer=framebuffers[i],
renderArea=render_area,
clearValueCount=1,
pClearValues=[clear_value])
vkCmdBeginRenderPass(command_buffer, render_pass_begin_create, VK_SUBPASS_CONTENTS_INLINE)
# Bing pipeline
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline)
# Draw
vkCmdDraw(command_buffer, 3, 1, 0, 0)
# End
vkCmdEndRenderPass(command_buffer)
vkEndCommandBuffer(command_buffer)
# Create semaphore
semaphore_create = VkSemaphoreCreateInfo(
sType=VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
flags=0)
semaphore_image_available = vkCreateSemaphore(logical_device, semaphore_create, None)
semaphore_render_finished = vkCreateSemaphore(logical_device, semaphore_create, None)
vkAcquireNextImageKHR = vkGetInstanceProcAddr(instance, "vkAcquireNextImageKHR")
vkQueuePresentKHR = vkGetInstanceProcAddr(instance, "vkQueuePresentKHR")
wait_semaphores = [semaphore_image_available]
wait_stages = [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT]
signal_semaphores = [semaphore_render_finished]
submit_create = VkSubmitInfo(
sType=VK_STRUCTURE_TYPE_SUBMIT_INFO,
waitSemaphoreCount=len(wait_semaphores),
pWaitSemaphores=wait_semaphores,
pWaitDstStageMask=wait_stages,
commandBufferCount=1,
pCommandBuffers=[command_buffers[0]],
signalSemaphoreCount=len(signal_semaphores),
pSignalSemaphores=signal_semaphores)
present_create = VkPresentInfoKHR(
sType=VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
waitSemaphoreCount=1,
pWaitSemaphores=signal_semaphores,
swapchainCount=1,
pSwapchains=[swapchain],
pImageIndices=[0],
pResults=None)
# optimization to avoid creating a new array each time
submit_list = ffi.new('VkSubmitInfo[1]', [submit_create])
def draw_frame():
try:
image_index = vkAcquireNextImageKHR(logical_device, swapchain, UINT64_MAX, semaphore_image_available, None)
except VkNotReady:
print('not ready')
return
submit_create.pCommandBuffers[0] = command_buffers[image_index]
vkQueueSubmit(graphic_queue, 1, submit_list, None)
present_create.pImageIndices[0] = image_index
vkQueuePresentKHR(presentation_queue, present_create)
# Fix #55 but downgrade performance -1000FPS)
vkQueueWaitIdle(presentation_queue)
# Main loop
running = True
if sys.version_info >= (3, 3):
clock = time.perf_counter
else:
clock = time.clock
last_time = clock() * 1000
fps = 0
while running:
fps += 1
if clock() * 1000 - last_time >= 1000:
last_time = clock() * 1000
print("FPS: %s" % fps)
fps = 0
events = sdl2.ext.get_events()
draw_frame()
for event in events:
if event.type == sdl2.SDL_QUIT:
running = False
vkDeviceWaitIdle(logical_device)
break
# ----------
# Clean everything
vkDestroySemaphore(logical_device, semaphore_image_available, None)
vkDestroySemaphore(logical_device, semaphore_render_finished, None)
vkDestroyCommandPool(logical_device, command_pool, None)
for f in framebuffers:
vkDestroyFramebuffer(logical_device, f, None)
vkDestroyPipeline(logical_device, pipeline, None)
vkDestroyPipelineLayout(logical_device, pipeline_layout, None)
vkDestroyRenderPass(logical_device, render_pass, None)
vkDestroyShaderModule(logical_device, frag_shader_module, None)
vkDestroyShaderModule(logical_device, vert_shader_module, None)
for i in image_views:
vkDestroyImageView(logical_device, i, None)
vkDestroySwapchainKHR(logical_device, swapchain, None)
vkDestroyDevice(logical_device, None)
vkDestroySurfaceKHR(instance, surface, None)
vkDestroyDebugReportCallbackEXT(instance, callback, None)
vkDestroyInstance(instance, None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment