Init
This commit is contained in:
120
examples/impl_glfw_metal.odin
Normal file
120
examples/impl_glfw_metal.odin
Normal file
@@ -0,0 +1,120 @@
|
||||
package impl_sdl2_metal
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
import mtl "vendor:darwin/Metal"
|
||||
import ns "core:sys/darwin/Foundation"
|
||||
import ca "vendor:darwin/QuartzCore"
|
||||
import glfw "vendor:glfw"
|
||||
import imgui ".."
|
||||
import imgui_glfw "../glfw"
|
||||
import imgui_mtl "../metal"
|
||||
|
||||
main :: proc() {
|
||||
run()
|
||||
}
|
||||
|
||||
glfw_error_cb :: proc "c" (error: i32, desc: cstring) {
|
||||
context = runtime.default_context()
|
||||
fmt.eprintln("[GLFW Error]", error, desc)
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
glfw.SetErrorCallback(glfw_error_cb)
|
||||
glfw.Init() or_return
|
||||
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API)
|
||||
|
||||
window := glfw.CreateWindow(1280, 720, "Test", nil, nil)
|
||||
if window == nil do return false
|
||||
|
||||
device := mtl.CreateSystemDefaultDevice()
|
||||
defer device->release()
|
||||
|
||||
command_queue := device->newCommandQueue()
|
||||
defer command_queue->release()
|
||||
|
||||
imgui_glfw.InitForOpenGL(window, true)
|
||||
imgui_mtl.Init(device)
|
||||
|
||||
ns_win := glfw.GetCocoaWindow(window)
|
||||
ns_view := glfw.GetCocoaView(window)
|
||||
|
||||
layer := ca.MetalLayer.layer()
|
||||
|
||||
layer->setDevice(device)
|
||||
layer->setPixelFormat(.BGRA8Unorm)
|
||||
|
||||
ns_view->setLayer(layer)
|
||||
ns_view->setWantsLayer(true)
|
||||
|
||||
render_pass_desc := mtl.RenderPassDescriptor.renderPassDescriptor()
|
||||
defer render_pass_desc->release()
|
||||
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
show_demo: b8 = true
|
||||
|
||||
for !glfw.WindowShouldClose(window) {
|
||||
glfw.PollEvents()
|
||||
|
||||
w, h: i32 = glfw.GetFramebufferSize(window)
|
||||
layer->setDrawableSize({width=ns.Float(w), height=ns.Float(h)})
|
||||
|
||||
drawable := layer->nextDrawable()
|
||||
defer drawable->release()
|
||||
|
||||
col_attachment := render_pass_desc->colorAttachments()->object(0)
|
||||
col_attachment->setClearColor(mtl.ClearColor{
|
||||
f64(clear_color[0] * clear_color[3]),
|
||||
f64(clear_color[1] * clear_color[3]),
|
||||
f64(clear_color[2] * clear_color[3]),
|
||||
f64(clear_color[3])})
|
||||
col_attachment->setTexture(drawable->texture())
|
||||
col_attachment->setLoadAction(.Clear)
|
||||
col_attachment->setStoreAction(.Store)
|
||||
|
||||
command_buffer := command_queue->commandBuffer()
|
||||
defer command_buffer->release()
|
||||
|
||||
render_encoder := command_buffer->renderCommandEncoderWithDescriptor(render_pass_desc)
|
||||
defer render_encoder->release()
|
||||
render_encoder->pushDebugGroup(ns.MakeConstantString("test"))
|
||||
|
||||
imgui_mtl.NewFrame(render_pass_desc)
|
||||
imgui_glfw.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.Button("Toggle DearImgui Demo") do show_demo = !show_demo
|
||||
if show_demo do imgui.ShowDemoWindow(&show_demo)
|
||||
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, .None)
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
imgui.Render()
|
||||
|
||||
|
||||
imgui_mtl.RenderDrawData(imgui.GetDrawData(), command_buffer, render_encoder);
|
||||
|
||||
render_encoder->popDebugGroup()
|
||||
render_encoder->endEncoding()
|
||||
|
||||
command_buffer->presentDrawable(drawable)
|
||||
command_buffer->commit()
|
||||
|
||||
}
|
||||
|
||||
imgui_mtl.Shutdown()
|
||||
imgui_glfw.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
glfw.DestroyWindow(window)
|
||||
glfw.Terminate()
|
||||
return true
|
||||
}
|
||||
88
examples/impl_glfw_opengl3.odin
Normal file
88
examples/impl_glfw_opengl3.odin
Normal file
@@ -0,0 +1,88 @@
|
||||
package impl_glfw_opengl3
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
import "vendor:glfw"
|
||||
import gl "vendor:OpenGL"
|
||||
import imgui ".."
|
||||
import imgui_glfw "../glfw"
|
||||
import imgui_gl3 "../opengl3"
|
||||
|
||||
main :: proc() {
|
||||
run()
|
||||
}
|
||||
|
||||
glfw_error_cb :: proc "c" (error: i32, desc: cstring) {
|
||||
context = runtime.default_context()
|
||||
fmt.eprintln("[GLFW Error]", error, desc)
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
glfw.SetErrorCallback(glfw_error_cb)
|
||||
glfw.Init() or_return
|
||||
|
||||
glsl_version: cstring = "#version 330"
|
||||
// glsl_version: cstring = "#version 130"
|
||||
glfw.WindowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
|
||||
glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR, 3)
|
||||
glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR, 2)
|
||||
glfw.WindowHint(glfw.OPENGL_FORWARD_COMPAT, true)
|
||||
|
||||
window := glfw.CreateWindow(1280, 720, "Test", nil, nil)
|
||||
if window == nil do return false
|
||||
glfw.MakeContextCurrent(window)
|
||||
glfw.SwapInterval(1)
|
||||
|
||||
gl.load_up_to(3, 3, glfw.gl_set_proc_address)
|
||||
|
||||
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
imgui_glfw.InitForOpenGL(window, true)
|
||||
imgui_gl3.InitEx(glsl_version)
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
show_demo: b8 = true
|
||||
|
||||
for !glfw.WindowShouldClose(window) {
|
||||
glfw.PollEvents()
|
||||
if glfw.GetWindowAttrib(window, glfw.ICONIFIED) != 0 {
|
||||
imgui_glfw.Sleep(10)
|
||||
continue
|
||||
}
|
||||
|
||||
imgui_gl3.NewFrame()
|
||||
imgui_glfw.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.Button("Toggle DearImgui Demo") do show_demo = !show_demo
|
||||
if show_demo do imgui.ShowDemoWindow(&show_demo)
|
||||
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, .None)
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
imgui.Render()
|
||||
|
||||
dw, dh:= glfw.GetFramebufferSize(window)
|
||||
gl.Viewport(0, 0, dw, dh)
|
||||
gl.ClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
imgui_gl3.RenderDrawData(imgui.GetDrawData());
|
||||
glfw.SwapBuffers(window);
|
||||
|
||||
}
|
||||
|
||||
imgui_gl3.Shutdown()
|
||||
imgui_glfw.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
glfw.DestroyWindow(window)
|
||||
glfw.Terminate()
|
||||
return true
|
||||
}
|
||||
410
examples/impl_glfw_vulkan.odin
Normal file
410
examples/impl_glfw_vulkan.odin
Normal file
@@ -0,0 +1,410 @@
|
||||
package impl_glfw_vulkan
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
import "core:bytes"
|
||||
import "base:runtime"
|
||||
import "vendor:glfw"
|
||||
import vk "vendor:vulkan"
|
||||
|
||||
import imgui ".."
|
||||
import imgui_glfw "../glfw"
|
||||
import imgui_vk "../vulkan"
|
||||
|
||||
vk_allocator: ^vk.AllocationCallbacks = nil
|
||||
vk_instance: vk.Instance = nil
|
||||
vk_physical_device: vk.PhysicalDevice = nil
|
||||
vk_device: vk.Device = nil
|
||||
vk_queue_family: u32 = max(u32)
|
||||
vk_queue: vk.Queue = nil
|
||||
vk_pipeline_cache: vk.PipelineCache = 0
|
||||
vk_descriptor_pool: vk.DescriptorPool = 0
|
||||
|
||||
imgui_vk_main_window_data: imgui_vk.Window
|
||||
imgui_vk_min_image_count: u32 = 2
|
||||
imgui_vk_swap_chain_rebuild: b32 = false
|
||||
|
||||
main :: proc() { run() }
|
||||
|
||||
vk_select_physical_device :: proc() -> vk.PhysicalDevice {
|
||||
vk_res: vk.Result
|
||||
gpu_count: u32 = 0
|
||||
|
||||
vk_res = vk.EnumeratePhysicalDevices(vk_instance, &gpu_count, nil)
|
||||
if !vk_res_ok(vk_res) do return nil
|
||||
|
||||
if gpu_count <= 0 {
|
||||
fmt.eprintln("no gpus found")
|
||||
return nil
|
||||
}
|
||||
|
||||
gpus := make([dynamic]vk.PhysicalDevice, gpu_count)
|
||||
vk_res = vk.EnumeratePhysicalDevices(vk_instance, &gpu_count, raw_data(gpus))
|
||||
if !vk_res_ok(vk_res) do return nil
|
||||
|
||||
for gpu, i in gpus {
|
||||
properties: vk.PhysicalDeviceProperties = {}
|
||||
vk.GetPhysicalDeviceProperties(gpu, &properties)
|
||||
if properties.deviceType == .DISCRETE_GPU do return gpu
|
||||
}
|
||||
|
||||
return gpus[0]
|
||||
}
|
||||
|
||||
is_ext_available :: proc(properties: [] vk.ExtensionProperties, extension: cstring)-> b32 {
|
||||
for &property in properties {
|
||||
if cstring(&property.extensionName[0]) == extension do return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
vk_res_ok :: proc(res: vk.Result) -> b32 {
|
||||
if res >= .SUCCESS {
|
||||
if res != .SUCCESS do fmt.eprintln("[VULKAN Info]", res)
|
||||
return true
|
||||
}
|
||||
|
||||
fmt.eprintln("[VULKAN Error]", res)
|
||||
return false
|
||||
}
|
||||
|
||||
glfw_error_cb :: proc "c" (error: i32, desc: cstring) {
|
||||
context = runtime.default_context()
|
||||
fmt.eprintln("[GLFW Error]", error, desc)
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
glfw.SetErrorCallback(glfw_error_cb)
|
||||
glfw.Init() or_return
|
||||
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API)
|
||||
|
||||
window := glfw.CreateWindow(
|
||||
1280,
|
||||
720,
|
||||
"Test",
|
||||
nil,
|
||||
nil
|
||||
)
|
||||
|
||||
glfw.VulkanSupported() or_return
|
||||
vk.load_proc_addresses(glfw.GetInstanceProcAddress(nil, "vkGetInstanceProcAddr"))
|
||||
vk_res: vk.Result
|
||||
extensions := make([dynamic]cstring)
|
||||
defer delete(extensions)
|
||||
for ext in glfw.GetRequiredInstanceExtensions() do append(&extensions, ext)
|
||||
|
||||
{
|
||||
create_info: vk.InstanceCreateInfo = {}
|
||||
create_info.sType = .INSTANCE_CREATE_INFO
|
||||
|
||||
properties_count: u32
|
||||
vk_res = vk.EnumerateInstanceExtensionProperties(nil, &properties_count, nil)
|
||||
vk_res_ok(vk_res) or_return
|
||||
|
||||
properties := make([dynamic]vk.ExtensionProperties, properties_count)
|
||||
defer delete(properties)
|
||||
vk_res = vk.EnumerateInstanceExtensionProperties(nil, &properties_count, raw_data(properties))
|
||||
vk_res_ok(vk_res) or_return
|
||||
|
||||
ext: cstring
|
||||
ext = vk.KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
|
||||
if is_ext_available(properties[:], ext) do append(&extensions, ext)
|
||||
ext = vk.KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
|
||||
if is_ext_available(properties[:], ext) {
|
||||
append(&extensions, ext)
|
||||
create_info.flags = create_info.flags + {.ENUMERATE_PORTABILITY_KHR}
|
||||
}
|
||||
|
||||
create_info.enabledExtensionCount = cast(u32)len(extensions)
|
||||
create_info.ppEnabledExtensionNames = raw_data(extensions)
|
||||
|
||||
vk_res = vk.CreateInstance(&create_info, vk_allocator, &vk_instance)
|
||||
vk_res_ok(vk_res) or_return
|
||||
}
|
||||
|
||||
vk.load_proc_addresses(vk_instance)
|
||||
vk_physical_device = vk_select_physical_device()
|
||||
|
||||
|
||||
{
|
||||
count: u32
|
||||
vk.GetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &count, nil)
|
||||
queues: [dynamic]vk.QueueFamilyProperties = make([dynamic]vk.QueueFamilyProperties, count)
|
||||
defer delete(queues)
|
||||
vk.GetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &count, raw_data(queues))
|
||||
for q_item, i in queues {
|
||||
if .GRAPHICS in q_item.queueFlags {
|
||||
vk_queue_family = u32(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if vk_queue_family == max(u32) do return false
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
device_extensions:= make([dynamic] cstring)
|
||||
defer delete(device_extensions)
|
||||
append(&device_extensions, "VK_KHR_swapchain")
|
||||
properties_count: u32
|
||||
vk.EnumerateDeviceExtensionProperties(vk_physical_device, nil, &properties_count, nil)
|
||||
properties := make([dynamic]vk.ExtensionProperties, properties_count)
|
||||
defer delete(properties)
|
||||
vk.EnumerateDeviceExtensionProperties(vk_physical_device, nil, &properties_count, raw_data(properties))
|
||||
|
||||
queue_priority: []f32 = { 1.0 }
|
||||
queue_info: [1]vk.DeviceQueueCreateInfo = {}
|
||||
queue_info[0].sType = .DEVICE_QUEUE_CREATE_INFO
|
||||
queue_info[0].queueFamilyIndex = vk_queue_family
|
||||
queue_info[0].queueCount = 1
|
||||
queue_info[0].pQueuePriorities = raw_data(queue_priority)
|
||||
create_info: vk.DeviceCreateInfo = {}
|
||||
create_info.sType = .DEVICE_CREATE_INFO
|
||||
create_info.queueCreateInfoCount = len(queue_info)
|
||||
create_info.pQueueCreateInfos = raw_data(queue_info[:])
|
||||
create_info.enabledExtensionCount = u32(len(device_extensions))
|
||||
create_info.ppEnabledExtensionNames = raw_data(device_extensions)
|
||||
vk_res = vk.CreateDevice(vk_physical_device, &create_info, vk_allocator, &vk_device)
|
||||
vk_res_ok(vk_res) or_return
|
||||
vk.GetDeviceQueue(vk_device, vk_queue_family, 0, &vk_queue)
|
||||
}
|
||||
vk.load_proc_addresses(vk_device)
|
||||
{
|
||||
pool_sizes: []vk.DescriptorPoolSize = {{.COMBINED_IMAGE_SAMPLER, 1}}
|
||||
pool_info: vk.DescriptorPoolCreateInfo = {}
|
||||
pool_info.sType = .DESCRIPTOR_POOL_CREATE_INFO
|
||||
pool_info.flags = {.FREE_DESCRIPTOR_SET}
|
||||
pool_info.maxSets = 1
|
||||
pool_info.poolSizeCount = u32(len(pool_sizes))
|
||||
pool_info.pPoolSizes = raw_data(pool_sizes)
|
||||
vk_res = vk.CreateDescriptorPool(vk_device, &pool_info, vk_allocator, &vk_descriptor_pool)
|
||||
vk_res_ok(vk_res) or_return
|
||||
}
|
||||
|
||||
|
||||
surface: vk.SurfaceKHR
|
||||
vk_res = glfw.CreateWindowSurface(vk_instance, window, vk_allocator, &surface)
|
||||
vk_res_ok(vk_res) or_return
|
||||
|
||||
imgui_window: ^imgui_vk.Window = &imgui_vk_main_window_data
|
||||
imgui_window.Surface = surface
|
||||
|
||||
response: b32
|
||||
vk_res = vk.GetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, vk_queue_family, surface, &response)
|
||||
vk_res_ok(vk_res) or_return
|
||||
if !response {
|
||||
fmt.eprintln("GetPhysicalDeviceSurfaceSupportKHR failed")
|
||||
return false
|
||||
}
|
||||
req_surface_img_fmt: [] vk.Format = {.B8G8R8A8_UNORM, .R8G8B8A8_UNORM, .B8G8R8_UNORM, .R8G8B8_UNORM}
|
||||
req_surface_color_space: vk.ColorSpaceKHR = .SRGB_NONLINEAR
|
||||
imgui_window.SurfaceFormat = imgui_vk.SelectSurfaceFormat(vk_physical_device, surface, raw_data(req_surface_img_fmt), i32(len(req_surface_img_fmt)), req_surface_color_space)
|
||||
|
||||
present_modes: [] vk.PresentModeKHR = {.MAILBOX, .IMMEDIATE, .FIFO}
|
||||
imgui_window.PresentMode = imgui_vk.SelectPresentMode(vk_physical_device, surface, raw_data(present_modes), i32(len(present_modes)))
|
||||
assert(imgui_vk_min_image_count >= 2)
|
||||
fb_w, fb_h := glfw.GetFramebufferSize(window)
|
||||
imgui_window.ClearEnable = true // This is enabled by default in Cpp; required for the attachment to clear
|
||||
imgui_vk.CreateOrResizeWindow(vk_instance, vk_physical_device, vk_device, imgui_window, vk_queue_family, vk_allocator, fb_w, fb_h, imgui_vk_min_image_count)
|
||||
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
imgui_glfw.InitForVulkan(window, true)
|
||||
init_info: imgui_vk.InitInfo = {}
|
||||
init_info.Instance = vk_instance
|
||||
init_info.PhysicalDevice = vk_physical_device
|
||||
init_info.Device = vk_device
|
||||
init_info.QueueFamily = vk_queue_family
|
||||
init_info.Queue = vk_queue
|
||||
init_info.PipelineCache = vk_pipeline_cache
|
||||
init_info.DescriptorPool = vk_descriptor_pool
|
||||
init_info.RenderPass = imgui_window.RenderPass
|
||||
init_info.Subpass = 0
|
||||
init_info.MinImageCount = imgui_vk_min_image_count
|
||||
init_info.ImageCount = imgui_window.ImageCount
|
||||
init_info.MSAASamples = {._1}
|
||||
init_info.Allocator = vk_allocator
|
||||
check_vk_res :: proc(res: vk.Result) { vk_res_ok(res) }
|
||||
init_info.CheckVkResultFn = check_vk_res
|
||||
imgui_vk.Init(&init_info)
|
||||
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
show_demo_window: b8 = true
|
||||
show_another_window: b8 = false
|
||||
_f: f32 = 0
|
||||
_counter: i32 = 0
|
||||
|
||||
|
||||
for !glfw.WindowShouldClose(window) {
|
||||
glfw.PollEvents()
|
||||
|
||||
|
||||
fb_w, fb_h = glfw.GetFramebufferSize(window)
|
||||
if fb_w > 0 && fb_h > 0 && (imgui_vk_swap_chain_rebuild || imgui_vk_main_window_data.Width != fb_w || imgui_vk_main_window_data.Height != fb_h) {
|
||||
imgui_vk.SetMinImageCount(imgui_vk_min_image_count)
|
||||
imgui_vk.CreateOrResizeWindow(vk_instance, vk_physical_device, vk_device, &imgui_vk_main_window_data, vk_queue_family, vk_allocator, fb_w, fb_h, imgui_vk_min_image_count)
|
||||
imgui_vk_main_window_data.FrameIndex = 0
|
||||
imgui_vk_swap_chain_rebuild = false
|
||||
}
|
||||
|
||||
if glfw.GetWindowAttrib(window, glfw.ICONIFIED) != 0 {
|
||||
imgui_glfw.Sleep(10)
|
||||
continue
|
||||
}
|
||||
|
||||
imgui_vk.NewFrame()
|
||||
imgui_glfw.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
|
||||
if show_demo_window do imgui.ShowDemoWindow(&show_demo_window)
|
||||
{
|
||||
|
||||
imgui.Begin("Hello, world!") // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
imgui.Text("This is some useful text.") // Display some text (you can use a format strings too)
|
||||
imgui.Checkbox("Demo Window", &show_demo_window) // Edit bools storing our window open/close state
|
||||
imgui.Checkbox("Another Window", &show_another_window)
|
||||
|
||||
imgui.SliderFloat("float", &_f, 0.0, 1.0) // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, {}) // Edit 3 floats representing a color
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
|
||||
|
||||
if imgui.Button("Button") do _counter += 1 // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
|
||||
imgui.SameLine()
|
||||
imgui.Text("counter = %d", _counter)
|
||||
|
||||
imgui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / io.Framerate, io.Framerate)
|
||||
imgui.End()
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if show_another_window {
|
||||
imgui.Begin("Another Window", &show_another_window) // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
imgui.Text("Hello from another window!")
|
||||
if imgui.Button("Close Me") do show_another_window = false
|
||||
imgui.End()
|
||||
}
|
||||
|
||||
|
||||
imgui.Render()
|
||||
|
||||
draw_data: ^imgui.ImDrawData = imgui.GetDrawData()
|
||||
is_minimized := draw_data.DisplaySize.x <= 0 || draw_data.DisplaySize.y <= 0
|
||||
if !is_minimized {
|
||||
imgui_window.ClearValue.color.float32.r = clear_color.r * clear_color.a
|
||||
imgui_window.ClearValue.color.float32.g = clear_color.g * clear_color.a
|
||||
imgui_window.ClearValue.color.float32.b = clear_color.b * clear_color.a
|
||||
imgui_window.ClearValue.color.float32.a = clear_color.a
|
||||
frame_render(imgui_window, draw_data)
|
||||
frame_present(imgui_window)
|
||||
}
|
||||
}
|
||||
vk_res = vk.DeviceWaitIdle(vk_device)
|
||||
vk_res_ok(vk_res) or_return
|
||||
imgui_vk.Shutdown()
|
||||
imgui_glfw.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
imgui_vk.DestroyWindow(vk_instance, vk_device, &imgui_vk_main_window_data, vk_allocator)
|
||||
vk.DestroyDescriptorPool(vk_device, vk_descriptor_pool, vk_allocator)
|
||||
vk.DestroyDevice(vk_device, vk_allocator)
|
||||
vk.DestroyInstance(vk_instance, vk_allocator)
|
||||
|
||||
glfw.DestroyWindow(window)
|
||||
glfw.Terminate()
|
||||
return true
|
||||
}
|
||||
|
||||
frame_render:: proc(imgui_vk_window: ^imgui_vk.Window, draw_data: ^imgui.ImDrawData) {
|
||||
vk_res: vk.Result
|
||||
|
||||
img_acquired_semaphore: vk.Semaphore = imgui_vk_window.FrameSemaphores[imgui_vk_window.SemaphoreIndex].ImageAcquiredSemaphore
|
||||
render_complete_semaphore: vk.Semaphore = imgui_vk_window.FrameSemaphores[imgui_vk_window.SemaphoreIndex].RenderCompleteSemaphore
|
||||
vk_res = vk.AcquireNextImageKHR(vk_device, imgui_vk_window.Swapchain, max(u64), img_acquired_semaphore, 0, &imgui_vk_window.FrameIndex)
|
||||
|
||||
if vk_res == .TIMEOUT do return
|
||||
if vk_res == .ERROR_OUT_OF_DATE_KHR || vk_res == .SUBOPTIMAL_KHR {
|
||||
imgui_vk_swap_chain_rebuild = true
|
||||
return
|
||||
}
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
fd: imgui_vk.Frame = imgui_vk_window.Frames[imgui_vk_window.FrameIndex]
|
||||
{
|
||||
|
||||
vk_res = vk.WaitForFences(vk_device, 1, &fd.Fence, true, max(u64))
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
vk_res = vk.ResetFences(vk_device, 1, &fd.Fence)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
{
|
||||
vk_res = vk.ResetCommandPool(vk_device, fd.CommandPool, {})
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
info: vk.CommandBufferBeginInfo = {}
|
||||
info.sType = .COMMAND_BUFFER_BEGIN_INFO
|
||||
info.flags = {.ONE_TIME_SUBMIT}
|
||||
vk_res = vk.BeginCommandBuffer(fd.CommandBuffer, &info)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
{
|
||||
info: vk.RenderPassBeginInfo = {}
|
||||
info.sType = .RENDER_PASS_BEGIN_INFO
|
||||
info.renderPass = imgui_vk_window.RenderPass
|
||||
info.framebuffer = fd.Framebuffer
|
||||
info.renderArea.extent.width = u32(imgui_vk_window.Width)
|
||||
info.renderArea.extent.height = u32(imgui_vk_window.Height)
|
||||
info.clearValueCount = 1
|
||||
info.pClearValues = &imgui_vk_window.ClearValue
|
||||
vk.CmdBeginRenderPass(fd.CommandBuffer, &info, .INLINE)
|
||||
}
|
||||
imgui_vk.RenderDrawData(draw_data, fd.CommandBuffer)
|
||||
vk.CmdEndRenderPass(fd.CommandBuffer)
|
||||
{
|
||||
wait_stage: vk.PipelineStageFlags = {.COLOR_ATTACHMENT_OUTPUT}
|
||||
info: vk.SubmitInfo = {}
|
||||
info.sType = .SUBMIT_INFO
|
||||
info.waitSemaphoreCount = 1
|
||||
info.pWaitSemaphores = &img_acquired_semaphore
|
||||
info.pWaitDstStageMask = &wait_stage
|
||||
info.commandBufferCount = 1
|
||||
info.pCommandBuffers = &fd.CommandBuffer
|
||||
info.signalSemaphoreCount = 1
|
||||
info.pSignalSemaphores = &render_complete_semaphore
|
||||
|
||||
vk_res = vk.EndCommandBuffer(fd.CommandBuffer)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
vk_res = vk.QueueSubmit(vk_queue, 1, &info, fd.Fence)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
}
|
||||
|
||||
frame_present:: proc(igvk_window: ^imgui_vk.Window) {
|
||||
vk_res: vk.Result
|
||||
if imgui_vk_swap_chain_rebuild do return
|
||||
render_complete_semaphore := igvk_window.FrameSemaphores[igvk_window.SemaphoreIndex].RenderCompleteSemaphore
|
||||
info: vk.PresentInfoKHR = {}
|
||||
info.sType = .PRESENT_INFO_KHR
|
||||
info.waitSemaphoreCount = 1
|
||||
info.pWaitSemaphores = &render_complete_semaphore
|
||||
info.swapchainCount = 1
|
||||
info.pSwapchains = &igvk_window.Swapchain
|
||||
info.pImageIndices = &igvk_window.FrameIndex
|
||||
vk_res = vk.QueuePresentKHR(vk_queue, &info)
|
||||
if vk_res == .ERROR_OUT_OF_DATE_KHR || vk_res == .SUBOPTIMAL_KHR {
|
||||
imgui_vk_swap_chain_rebuild = true
|
||||
return
|
||||
}
|
||||
if !vk_res_ok(vk_res) do return
|
||||
igvk_window.SemaphoreIndex = (igvk_window.SemaphoreIndex + 1) % igvk_window.SemaphoreCount
|
||||
}
|
||||
31
examples/impl_null.odin
Normal file
31
examples/impl_null.odin
Normal file
@@ -0,0 +1,31 @@
|
||||
package impl_null
|
||||
import "core:fmt"
|
||||
import imgui ".."
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("CreateContext()")
|
||||
imgui.CreateContext()
|
||||
io := imgui.GetIO()
|
||||
|
||||
tex_pixels: cstring
|
||||
tex_w, tex_h: i32
|
||||
imgui.ImFontAtlas_GetTexDataAsRGBA32(io.Fonts, &tex_pixels, &tex_w, &tex_h, nil)
|
||||
for n: i32 = 0; n < 20; n += 1 {
|
||||
fmt.println("NewFrame()", n)
|
||||
io.DisplaySize.x = 1920
|
||||
io.DisplaySize.y = 1920
|
||||
io.DeltaTime = 1.0 / 60.0
|
||||
imgui.NewFrame()
|
||||
|
||||
f: f32 = 0.0
|
||||
imgui.Text("Hello, world!")
|
||||
imgui.SliderFloat("float", &f, 0.0, 1.0)
|
||||
imgui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / io.Framerate, io.Framerate)
|
||||
imgui.ShowDemoWindow()
|
||||
|
||||
imgui.Render()
|
||||
}
|
||||
|
||||
fmt.println("DestroyContext()")
|
||||
imgui.DestroyContext()
|
||||
}
|
||||
125
examples/impl_sdl2_metal.odin
Normal file
125
examples/impl_sdl2_metal.odin
Normal file
@@ -0,0 +1,125 @@
|
||||
package impl_sdl2_metal
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
import mtl "vendor:darwin/Metal"
|
||||
import ns "core:sys/darwin/Foundation"
|
||||
import ca "vendor:darwin/QuartzCore"
|
||||
import sdl "vendor:sdl2"
|
||||
import imgui ".."
|
||||
import imgui_sdl2 "../sdl2"
|
||||
import imgui_mtl "../metal"
|
||||
|
||||
main :: proc() {
|
||||
run()
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
if sdl.Init({.VIDEO, .GAMECONTROLLER, .TIMER}) != 0 {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
sdl.SetHint(sdl.HINT_RENDER_DRIVER, "metal")
|
||||
window := sdl.CreateWindow("Test", sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, 1280, 720, {.METAL, .RESIZABLE, .ALLOW_HIGHDPI})
|
||||
if window == nil {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
renderer := sdl.CreateRenderer(window, -1, {.ACCELERATED, .PRESENTVSYNC})
|
||||
if renderer == nil {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
layer: ^ca.MetalLayer = cast(^ca.MetalLayer)sdl.RenderGetMetalLayer(renderer)
|
||||
layer->setPixelFormat(.BGRA8Unorm)
|
||||
device := layer->device()
|
||||
defer device->release()
|
||||
imgui_mtl.Init(device)
|
||||
imgui_sdl2.InitForMetal(window)
|
||||
|
||||
command_queue := layer->device()->newCommandQueue()
|
||||
defer command_queue->release()
|
||||
|
||||
render_pass_desc := mtl.RenderPassDescriptor.renderPassDescriptor()
|
||||
defer render_pass_desc->release()
|
||||
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
done: b32 = false
|
||||
show_demo: b8 = true
|
||||
|
||||
for !done {
|
||||
|
||||
event: sdl.Event
|
||||
for sdl.PollEvent(&event) {
|
||||
imgui_sdl2.ProcessEvent(&event)
|
||||
|
||||
if event.type == .QUIT do done = true
|
||||
if event.type == .WINDOWEVENT && event.window.event == .CLOSE do done = true
|
||||
}
|
||||
|
||||
w, h: i32
|
||||
sdl.GetRendererOutputSize(renderer, &w, &h)
|
||||
layer->setDrawableSize({width=ns.Float(w), height=ns.Float(h)})
|
||||
|
||||
drawable := layer->nextDrawable()
|
||||
defer drawable->release()
|
||||
|
||||
col_attachment := render_pass_desc->colorAttachments()->object(0)
|
||||
col_attachment->setClearColor(mtl.ClearColor{
|
||||
f64(clear_color[0] * clear_color[3]),
|
||||
f64(clear_color[1] * clear_color[3]),
|
||||
f64(clear_color[2] * clear_color[3]),
|
||||
f64(clear_color[3])})
|
||||
col_attachment->setTexture(drawable->texture())
|
||||
col_attachment->setLoadAction(.Clear)
|
||||
col_attachment->setStoreAction(.Store)
|
||||
|
||||
command_buffer := command_queue->commandBuffer()
|
||||
defer command_buffer->release()
|
||||
|
||||
render_encoder := command_buffer->renderCommandEncoderWithDescriptor(render_pass_desc)
|
||||
defer render_encoder->release()
|
||||
render_encoder->pushDebugGroup(ns.MakeConstantString("test"))
|
||||
|
||||
imgui_mtl.NewFrame(render_pass_desc)
|
||||
imgui_sdl2.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.Button("Toggle DearImgui Demo") do show_demo = !show_demo
|
||||
if show_demo do imgui.ShowDemoWindow(&show_demo)
|
||||
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, .None)
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
imgui.Render()
|
||||
|
||||
|
||||
imgui_mtl.RenderDrawData(imgui.GetDrawData(), command_buffer, render_encoder);
|
||||
|
||||
render_encoder->popDebugGroup()
|
||||
render_encoder->endEncoding()
|
||||
|
||||
command_buffer->presentDrawable(drawable)
|
||||
command_buffer->commit()
|
||||
|
||||
}
|
||||
|
||||
imgui_mtl.Shutdown()
|
||||
imgui_sdl2.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
sdl.DestroyRenderer(renderer)
|
||||
sdl.DestroyWindow(window)
|
||||
sdl.Quit()
|
||||
return true
|
||||
}
|
||||
100
examples/impl_sdl2_opengl3.odin
Normal file
100
examples/impl_sdl2_opengl3.odin
Normal file
@@ -0,0 +1,100 @@
|
||||
package impl_sdl2_opengl3
|
||||
import os "core:os"
|
||||
import fmt "core:fmt"
|
||||
import sdl "vendor:sdl2"
|
||||
import gl "vendor:OpenGL"
|
||||
import imgui ".."
|
||||
import imgui_sdl2 "../sdl2"
|
||||
import imgui_gl3 "../opengl3"
|
||||
|
||||
main :: proc() {
|
||||
run()
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
if sdl.Init({.VIDEO, .GAMECONTROLLER, .TIMER}) != 0 {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
glsl_version: cstring = "#version 330"
|
||||
sdl.GL_SetAttribute(.CONTEXT_FLAGS, 0)
|
||||
sdl.GL_SetAttribute(.CONTEXT_PROFILE_MASK, i32(sdl.GLprofile.CORE))
|
||||
sdl.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, 3)
|
||||
sdl.GL_SetAttribute(.CONTEXT_MINOR_VERSION, 0)
|
||||
|
||||
sdl.GL_SetAttribute(.DOUBLEBUFFER, 1)
|
||||
sdl.GL_SetAttribute(.DEPTH_SIZE, 24)
|
||||
sdl.GL_SetAttribute(.STENCIL_SIZE, 8)
|
||||
|
||||
window_flags: sdl.WindowFlags = {.OPENGL, .RESIZABLE, .HIDDEN, .ALLOW_HIGHDPI}
|
||||
window := sdl.CreateWindow("Test", sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, 1280, 720, window_flags)
|
||||
if window == nil {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
gl_ctx := sdl.GL_CreateContext(window)
|
||||
if gl_ctx == nil {
|
||||
fmt.eprintln(sdl.GetError())
|
||||
return false
|
||||
}
|
||||
|
||||
sdl.GL_MakeCurrent(window, gl_ctx)
|
||||
gl.load_up_to(3, 3, sdl.gl_set_proc_address)
|
||||
|
||||
sdl.GL_SetSwapInterval(1)
|
||||
sdl.ShowWindow(window)
|
||||
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
imgui_sdl2.InitForOpenGL(window, gl_ctx)
|
||||
imgui_gl3.InitEx(glsl_version)
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
done: b32 = false
|
||||
show_demo: b8 = true
|
||||
|
||||
for !done {
|
||||
event: sdl.Event
|
||||
for sdl.PollEvent(&event) {
|
||||
imgui_sdl2.ProcessEvent(&event)
|
||||
if event.type == .QUIT do done = true
|
||||
if event.type == .WINDOWEVENT && event.window.event == .CLOSE do done = true
|
||||
}
|
||||
|
||||
imgui_gl3.NewFrame()
|
||||
imgui_sdl2.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.Button("Toggle DearImgui Demo") do show_demo = !show_demo
|
||||
if show_demo do imgui.ShowDemoWindow(&show_demo)
|
||||
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, .None)
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
imgui.Render()
|
||||
|
||||
gl.Viewport(0, 0, i32(io.DisplaySize.x), i32(io.DisplaySize.y))
|
||||
gl.ClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
imgui_gl3.RenderDrawData(imgui.GetDrawData());
|
||||
sdl.GL_SwapWindow(window);
|
||||
|
||||
}
|
||||
|
||||
imgui_gl3.Shutdown()
|
||||
imgui_sdl2.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
sdl.GL_DeleteContext(gl_ctx)
|
||||
sdl.DestroyWindow(window)
|
||||
sdl.Quit()
|
||||
return true
|
||||
}
|
||||
403
examples/impl_sdl2_vulkan.odin
Normal file
403
examples/impl_sdl2_vulkan.odin
Normal file
@@ -0,0 +1,403 @@
|
||||
package impl_sdl2_vulkan
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
import "core:bytes"
|
||||
|
||||
import imgui ".."
|
||||
import imgui_vk "../vulkan"
|
||||
import imgui_sdl2 "../sdl2"
|
||||
import sdl "vendor:sdl2"
|
||||
import vk "vendor:vulkan"
|
||||
|
||||
vk_allocator: ^vk.AllocationCallbacks = nil
|
||||
vk_instance: vk.Instance = nil
|
||||
vk_physical_device: vk.PhysicalDevice = nil
|
||||
vk_device: vk.Device = nil
|
||||
vk_queue_family: u32 = max(u32)
|
||||
vk_queue: vk.Queue = nil
|
||||
vk_debugreport: vk.DebugReportCallbackEXT = 0
|
||||
vk_pipeline_cache: vk.PipelineCache = 0
|
||||
vk_descriptor_pool: vk.DescriptorPool = 0
|
||||
|
||||
imgui_vk_main_window_data: imgui_vk.Window
|
||||
imgui_vk_min_image_count: u32 = 2
|
||||
imgui_vk_swap_chain_rebuild: b32 = false
|
||||
|
||||
main :: proc() { run() }
|
||||
|
||||
vk_select_physical_device :: proc() -> vk.PhysicalDevice {
|
||||
vk_res: vk.Result
|
||||
gpu_count: u32 = 0
|
||||
|
||||
vk_res = vk.EnumeratePhysicalDevices(vk_instance, &gpu_count, nil)
|
||||
if !vk_res_ok(vk_res) do return nil
|
||||
|
||||
if gpu_count <= 0 {
|
||||
fmt.eprintln("no gpus found")
|
||||
return nil
|
||||
}
|
||||
|
||||
gpus := make([dynamic]vk.PhysicalDevice, gpu_count)
|
||||
vk_res = vk.EnumeratePhysicalDevices(vk_instance, &gpu_count, raw_data(gpus))
|
||||
if !vk_res_ok(vk_res) do return nil
|
||||
|
||||
for gpu, i in gpus {
|
||||
properties: vk.PhysicalDeviceProperties = {}
|
||||
vk.GetPhysicalDeviceProperties(gpu, &properties)
|
||||
if properties.deviceType == .DISCRETE_GPU do return gpu
|
||||
}
|
||||
|
||||
return gpus[0]
|
||||
}
|
||||
|
||||
is_ext_available :: proc(properties: [] vk.ExtensionProperties, extension: cstring)-> b32 {
|
||||
for &property in properties {
|
||||
if cstring(&property.extensionName[0]) == extension do return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
vk_res_ok :: proc(res: vk.Result) -> b32 {
|
||||
if res >= .SUCCESS {
|
||||
if res != .SUCCESS do fmt.eprintln("[VULKAN Info]", res)
|
||||
return true
|
||||
}
|
||||
|
||||
fmt.eprintln("[VULKAN Error]", res)
|
||||
return false
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
window := sdl.CreateWindow(
|
||||
"Test",
|
||||
sdl.WINDOWPOS_CENTERED,
|
||||
sdl.WINDOWPOS_CENTERED,
|
||||
1280,
|
||||
720,
|
||||
{.VULKAN, .RESIZABLE, .ALLOW_HIGHDPI}
|
||||
)
|
||||
defer sdl.DestroyWindow(window)
|
||||
|
||||
vk.load_proc_addresses(sdl.Vulkan_GetVkGetInstanceProcAddr())
|
||||
|
||||
vk_res: vk.Result
|
||||
sdl_res: sdl.bool
|
||||
|
||||
extensions_count: u32
|
||||
sdl_res = sdl.Vulkan_GetInstanceExtensions(window, &extensions_count, nil)
|
||||
|
||||
extensions := make([dynamic]cstring, extensions_count)
|
||||
defer delete(extensions)
|
||||
sdl_res = sdl.Vulkan_GetInstanceExtensions(window, &extensions_count, raw_data(extensions))
|
||||
|
||||
{
|
||||
create_info: vk.InstanceCreateInfo = {}
|
||||
create_info.sType = .INSTANCE_CREATE_INFO
|
||||
|
||||
properties_count: u32
|
||||
vk_res = vk.EnumerateInstanceExtensionProperties(nil, &properties_count, nil)
|
||||
vk_res_ok(vk_res) or_return
|
||||
|
||||
properties := make([dynamic]vk.ExtensionProperties, properties_count)
|
||||
defer delete(properties)
|
||||
vk_res = vk.EnumerateInstanceExtensionProperties(nil, &properties_count, raw_data(properties))
|
||||
vk_res_ok(vk_res) or_return
|
||||
|
||||
ext: cstring
|
||||
ext = vk.KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
|
||||
if is_ext_available(properties[:], ext) do append(&extensions, ext)
|
||||
ext = vk.KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
|
||||
if is_ext_available(properties[:], ext) {
|
||||
append(&extensions, ext)
|
||||
create_info.flags = create_info.flags + {.ENUMERATE_PORTABILITY_KHR}
|
||||
}
|
||||
|
||||
create_info.enabledExtensionCount = cast(u32)len(extensions)
|
||||
create_info.ppEnabledExtensionNames = raw_data(extensions)
|
||||
|
||||
vk_res = vk.CreateInstance(&create_info, vk_allocator, &vk_instance);
|
||||
vk_res_ok(vk_res) or_return
|
||||
}
|
||||
|
||||
vk.load_proc_addresses(vk_instance)
|
||||
vk_physical_device = vk_select_physical_device()
|
||||
|
||||
|
||||
{
|
||||
count: u32
|
||||
vk.GetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &count, nil)
|
||||
queues: [dynamic]vk.QueueFamilyProperties = make([dynamic]vk.QueueFamilyProperties, count)
|
||||
defer delete(queues)
|
||||
vk.GetPhysicalDeviceQueueFamilyProperties(vk_physical_device, &count, raw_data(queues))
|
||||
for q_item, i in queues {
|
||||
if .GRAPHICS in q_item.queueFlags {
|
||||
vk_queue_family = u32(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if vk_queue_family == max(u32) do return false
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
device_extensions:= make([dynamic] cstring)
|
||||
defer delete(device_extensions)
|
||||
append(&device_extensions, "VK_KHR_swapchain")
|
||||
properties_count: u32
|
||||
vk.EnumerateDeviceExtensionProperties(vk_physical_device, nil, &properties_count, nil)
|
||||
properties := make([dynamic]vk.ExtensionProperties, properties_count)
|
||||
defer delete(properties)
|
||||
vk.EnumerateDeviceExtensionProperties(vk_physical_device, nil, &properties_count, raw_data(properties))
|
||||
|
||||
queue_priority: []f32 = { 1.0 }
|
||||
queue_info: [1]vk.DeviceQueueCreateInfo = {}
|
||||
queue_info[0].sType = .DEVICE_QUEUE_CREATE_INFO
|
||||
queue_info[0].queueFamilyIndex = vk_queue_family
|
||||
queue_info[0].queueCount = 1
|
||||
queue_info[0].pQueuePriorities = raw_data(queue_priority)
|
||||
create_info: vk.DeviceCreateInfo = {}
|
||||
create_info.sType = .DEVICE_CREATE_INFO
|
||||
create_info.queueCreateInfoCount = len(queue_info)
|
||||
create_info.pQueueCreateInfos = raw_data(queue_info[:])
|
||||
create_info.enabledExtensionCount = u32(len(device_extensions))
|
||||
create_info.ppEnabledExtensionNames = raw_data(device_extensions)
|
||||
vk_res = vk.CreateDevice(vk_physical_device, &create_info, vk_allocator, &vk_device)
|
||||
vk_res_ok(vk_res) or_return
|
||||
vk.GetDeviceQueue(vk_device, vk_queue_family, 0, &vk_queue)
|
||||
}
|
||||
vk.load_proc_addresses(vk_device)
|
||||
{
|
||||
pool_sizes: []vk.DescriptorPoolSize = {{.COMBINED_IMAGE_SAMPLER, 1}}
|
||||
pool_info: vk.DescriptorPoolCreateInfo = {}
|
||||
pool_info.sType = .DESCRIPTOR_POOL_CREATE_INFO
|
||||
pool_info.flags = {.FREE_DESCRIPTOR_SET}
|
||||
pool_info.maxSets = 1
|
||||
pool_info.poolSizeCount = u32(len(pool_sizes))
|
||||
pool_info.pPoolSizes = raw_data(pool_sizes)
|
||||
vk_res = vk.CreateDescriptorPool(vk_device, &pool_info, vk_allocator, &vk_descriptor_pool)
|
||||
vk_res_ok(vk_res) or_return
|
||||
}
|
||||
|
||||
|
||||
surface: vk.SurfaceKHR
|
||||
sdl.Vulkan_CreateSurface(window, vk_instance, &surface) or_return
|
||||
|
||||
imgui_window: ^imgui_vk.Window = &imgui_vk_main_window_data
|
||||
imgui_window.Surface = surface
|
||||
|
||||
response: b32
|
||||
vk_res = vk.GetPhysicalDeviceSurfaceSupportKHR(vk_physical_device, vk_queue_family, surface, &response)
|
||||
vk_res_ok(vk_res) or_return
|
||||
if !response {
|
||||
fmt.eprintln("GetPhysicalDeviceSurfaceSupportKHR failed")
|
||||
return false
|
||||
}
|
||||
req_surface_img_fmt: [] vk.Format = {.B8G8R8A8_UNORM, .R8G8B8A8_UNORM, .B8G8R8_UNORM, .R8G8B8_UNORM}
|
||||
req_surface_color_space: vk.ColorSpaceKHR = .SRGB_NONLINEAR
|
||||
imgui_window.SurfaceFormat = imgui_vk.SelectSurfaceFormat(vk_physical_device, surface, raw_data(req_surface_img_fmt), i32(len(req_surface_img_fmt)), req_surface_color_space);
|
||||
|
||||
present_modes: [] vk.PresentModeKHR = {.MAILBOX, .IMMEDIATE, .FIFO}
|
||||
imgui_window.PresentMode = imgui_vk.SelectPresentMode(vk_physical_device, surface, &present_modes[0], i32(len(present_modes)))
|
||||
assert(imgui_vk_min_image_count >= 2)
|
||||
w,h: i32
|
||||
sdl.GetWindowSize(window, &w, &h)
|
||||
imgui_window.ClearEnable = true // This is enabled by default in Cpp; required for the attachment to clear
|
||||
imgui_vk.CreateOrResizeWindow(vk_instance, vk_physical_device, vk_device, imgui_window, vk_queue_family, vk_allocator, w, h, imgui_vk_min_image_count)
|
||||
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
imgui_sdl2.InitForVulkan(window)
|
||||
init_info: imgui_vk.InitInfo = {}
|
||||
init_info.Allocator = vk_allocator
|
||||
check_vk_res :: proc(res: vk.Result) { vk_res_ok(res) }
|
||||
init_info.CheckVkResultFn = check_vk_res
|
||||
init_info.DescriptorPool = vk_descriptor_pool
|
||||
init_info.Device = vk_device
|
||||
init_info.ImageCount = imgui_window.ImageCount
|
||||
init_info.Instance = vk_instance
|
||||
init_info.MSAASamples = {._1}
|
||||
init_info.MinImageCount = imgui_vk_min_image_count
|
||||
init_info.PhysicalDevice = vk_physical_device
|
||||
init_info.PipelineCache = vk_pipeline_cache
|
||||
init_info.Queue = vk_queue
|
||||
init_info.QueueFamily = vk_queue_family
|
||||
init_info.RenderPass = imgui_window.RenderPass
|
||||
init_info.Subpass = 0
|
||||
imgui_vk.Init(&init_info)
|
||||
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
show_demo_window: b8 = true
|
||||
show_another_window: b8 = false
|
||||
_f: f32 = 0
|
||||
_counter: i32 = 0
|
||||
|
||||
done: b32 = false
|
||||
for !done {
|
||||
event: sdl.Event
|
||||
for sdl.PollEvent(&event) {
|
||||
imgui_sdl2.ProcessEvent(&event)
|
||||
if event.type == .QUIT do done = true
|
||||
if event.type == .WINDOWEVENT && event.window.event == .CLOSE do done = true
|
||||
}
|
||||
|
||||
fb_w, fb_h: i32
|
||||
sdl.GetWindowSize(window, &fb_w, &fb_h)
|
||||
if fb_w > 0 && fb_h > 0 && (imgui_vk_swap_chain_rebuild || imgui_vk_main_window_data.Width != fb_w || imgui_vk_main_window_data.Height != fb_h) {
|
||||
imgui_vk.SetMinImageCount(imgui_vk_min_image_count)
|
||||
imgui_vk.CreateOrResizeWindow(vk_instance, vk_physical_device, vk_device, &imgui_vk_main_window_data, vk_queue_family, vk_allocator, fb_w, fb_h, imgui_vk_min_image_count)
|
||||
imgui_vk_main_window_data.FrameIndex = 0
|
||||
imgui_vk_swap_chain_rebuild = false
|
||||
}
|
||||
|
||||
imgui_sdl2.NewFrame()
|
||||
imgui_vk.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if show_demo_window do imgui.ShowDemoWindow(&show_demo_window)
|
||||
{
|
||||
|
||||
imgui.Begin("Hello, world!") // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
imgui.Text("This is some useful text.") // Display some text (you can use a format strings too)
|
||||
imgui.Checkbox("Demo Window", &show_demo_window) // Edit bools storing our window open/close state
|
||||
imgui.Checkbox("Another Window", &show_another_window)
|
||||
|
||||
imgui.SliderFloat("float", &_f, 0.0, 1.0) // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, {}) // Edit 3 floats representing a color
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
|
||||
|
||||
if imgui.Button("Button") do _counter += 1 // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
|
||||
imgui.SameLine()
|
||||
imgui.Text("counter = %d", _counter)
|
||||
|
||||
imgui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / io.Framerate, io.Framerate)
|
||||
imgui.End()
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if show_another_window {
|
||||
imgui.Begin("Another Window", &show_another_window) // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
imgui.Text("Hello from another window!")
|
||||
if imgui.Button("Close Me") do show_another_window = false
|
||||
imgui.End()
|
||||
}
|
||||
|
||||
imgui.Render()
|
||||
|
||||
draw_data: ^imgui.ImDrawData = imgui.GetDrawData()
|
||||
|
||||
imgui_window.ClearValue.color.float32[0] = clear_color.x * clear_color.w;
|
||||
imgui_window.ClearValue.color.float32[1] = clear_color.y * clear_color.w;
|
||||
imgui_window.ClearValue.color.float32[2] = clear_color.z * clear_color.w;
|
||||
imgui_window.ClearValue.color.float32[3] = clear_color.w;
|
||||
frame_render(imgui_window, draw_data)
|
||||
frame_present(imgui_window)
|
||||
|
||||
|
||||
}
|
||||
|
||||
imgui_vk.DestroyWindow(vk_instance, vk_device, &imgui_vk_main_window_data, vk_allocator);
|
||||
|
||||
vk.DestroyDescriptorPool(vk_device, vk_descriptor_pool, vk_allocator)
|
||||
vk.DestroyDevice(vk_device, vk_allocator)
|
||||
vk.DestroyInstance(vk_instance, vk_allocator)
|
||||
|
||||
sdl.DestroyWindow(window)
|
||||
sdl.Quit()
|
||||
return true
|
||||
}
|
||||
|
||||
frame_render:: proc(igvk_window: ^imgui_vk.Window, draw_data: ^imgui.ImDrawData) {
|
||||
vk_res: vk.Result
|
||||
|
||||
img_acquired_semaphore: vk.Semaphore = igvk_window.FrameSemaphores[igvk_window.SemaphoreIndex].ImageAcquiredSemaphore
|
||||
render_complete_semaphore: vk.Semaphore = igvk_window.FrameSemaphores[igvk_window.SemaphoreIndex].RenderCompleteSemaphore
|
||||
vk_res = vk.AcquireNextImageKHR(vk_device, igvk_window.Swapchain, max(u64), img_acquired_semaphore, 0, &igvk_window.FrameIndex)
|
||||
|
||||
if vk_res == .ERROR_OUT_OF_DATE_KHR || vk_res == .SUBOPTIMAL_KHR {
|
||||
imgui_vk_swap_chain_rebuild = true
|
||||
return
|
||||
}
|
||||
if vk_res == .TIMEOUT do return
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
fd: imgui_vk.Frame = igvk_window.Frames[igvk_window.FrameIndex]
|
||||
{
|
||||
|
||||
vk_res = vk.WaitForFences(vk_device, 1, &fd.Fence, true, max(u64))
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
vk_res = vk.ResetFences(vk_device, 1, &fd.Fence)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
{
|
||||
vk_res = vk.ResetCommandPool(vk_device, fd.CommandPool, {})
|
||||
if !vk_res_ok(vk_res) do return
|
||||
|
||||
info: vk.CommandBufferBeginInfo = {}
|
||||
info.sType = .COMMAND_BUFFER_BEGIN_INFO
|
||||
info.flags = {.ONE_TIME_SUBMIT}
|
||||
vk_res = vk.BeginCommandBuffer(fd.CommandBuffer, &info)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
{
|
||||
info: vk.RenderPassBeginInfo = {}
|
||||
info.sType = .RENDER_PASS_BEGIN_INFO
|
||||
info.renderPass = igvk_window.RenderPass
|
||||
info.framebuffer = fd.Framebuffer
|
||||
info.renderArea.extent.width = u32(igvk_window.Width)
|
||||
info.renderArea.extent.height = u32(igvk_window.Height)
|
||||
info.clearValueCount = 1
|
||||
info.pClearValues = &igvk_window.ClearValue
|
||||
vk.CmdBeginRenderPass(fd.CommandBuffer, &info, .INLINE)
|
||||
}
|
||||
|
||||
imgui_vk.RenderDrawData(draw_data, fd.CommandBuffer)
|
||||
vk.CmdEndRenderPass(fd.CommandBuffer)
|
||||
|
||||
{
|
||||
wait_stage: vk.PipelineStageFlags = {.COLOR_ATTACHMENT_OUTPUT}
|
||||
info: vk.SubmitInfo = {}
|
||||
info.sType = .SUBMIT_INFO
|
||||
info.waitSemaphoreCount = 1
|
||||
info.pWaitSemaphores = &img_acquired_semaphore
|
||||
info.pWaitDstStageMask = &wait_stage
|
||||
info.commandBufferCount = 1
|
||||
info.pCommandBuffers = &fd.CommandBuffer
|
||||
info.signalSemaphoreCount = 1
|
||||
info.pSignalSemaphores = &render_complete_semaphore
|
||||
vk_res = vk.EndCommandBuffer(fd.CommandBuffer)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
vk_res = vk.QueueSubmit(vk_queue, 1, &info, fd.Fence)
|
||||
if !vk_res_ok(vk_res) do return
|
||||
}
|
||||
}
|
||||
|
||||
frame_present:: proc(igvk_window: ^imgui_vk.Window) {
|
||||
vk_res: vk.Result
|
||||
if imgui_vk_swap_chain_rebuild do return
|
||||
render_complete_semaphore := igvk_window.FrameSemaphores[igvk_window.SemaphoreIndex].RenderCompleteSemaphore
|
||||
info: vk.PresentInfoKHR = {}
|
||||
info.sType = .PRESENT_INFO_KHR
|
||||
info.waitSemaphoreCount = 1
|
||||
info.pWaitSemaphores = &render_complete_semaphore
|
||||
info.swapchainCount = 1
|
||||
info.pSwapchains = &igvk_window.Swapchain
|
||||
info.pImageIndices = &igvk_window.FrameIndex
|
||||
vk_res = vk.QueuePresentKHR(vk_queue, &info)
|
||||
if vk_res == .ERROR_OUT_OF_DATE_KHR || vk_res == .SUBOPTIMAL_KHR {
|
||||
imgui_vk_swap_chain_rebuild = true
|
||||
return
|
||||
}
|
||||
if !vk_res_ok(vk_res) do return
|
||||
igvk_window.SemaphoreIndex = (igvk_window.SemaphoreIndex + 1) % igvk_window.SemaphoreCount
|
||||
}
|
||||
91
examples/impl_win32_opengl3.odin
Normal file
91
examples/impl_win32_opengl3.odin
Normal file
@@ -0,0 +1,91 @@
|
||||
package impl_wini32_opengl3
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
import win32 "core:sys/windows"
|
||||
import gl "vendor:OpenGL"
|
||||
import imgui ".."
|
||||
import imgui_win32 "../win32"
|
||||
import imgui_gl3 "../opengl3"
|
||||
|
||||
main :: proc() {
|
||||
run()
|
||||
}
|
||||
|
||||
win32_hrc: win32.HGLRC
|
||||
win32_main_window: win32.HDC
|
||||
win32_width: i32
|
||||
win32_height: i32
|
||||
|
||||
win32_gl_create :: proc(hwnd: win32.HWND, data: win32.HDC) -> b8
|
||||
{
|
||||
hdc: win32.HDC = win32.GetDC(hwnd)
|
||||
pfd: win32.PIXELFORMATDESCRIPTOR = {}
|
||||
pfd.nSize = size_of(pfd)
|
||||
pfd.nVersion = 1
|
||||
pfd.dwFlags = 0 // TODO flags
|
||||
pfd.iPixelType = 0 // more flags
|
||||
pfd.cColorBits = 32
|
||||
|
||||
pf: i32 = win32.ChoosePixelFormat(hdc, &pfd)
|
||||
if pf == 0 do return false
|
||||
if !win32.SetPixelFormat(hdc, pf, &pfd) do return false
|
||||
win32.ReleaseDC(hwnd, hdc)
|
||||
data = win32.GetDC(hwnd)
|
||||
if win32_hrc == 0 do win32_hrc = win32.wglCreateContext(data)
|
||||
return true
|
||||
}
|
||||
|
||||
run :: proc() -> b32 {
|
||||
wc: win32.WNDCLASSEXW = {}
|
||||
|
||||
imgui.CreateContext(nil)
|
||||
io := imgui.GetIO()
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableKeyboard
|
||||
io.ConfigFlags |= imgui.ConfigFlags.NavEnableGamepad
|
||||
imgui.StyleColorsDark(nil)
|
||||
|
||||
imgui_glfw.InitForOpenGL(window, true)
|
||||
imgui_gl3.InitEx(glsl_version)
|
||||
clear_color: [4]f32 = {0.45, 0.55, 0.60, 1.00}
|
||||
_cc := clear_color.xyz
|
||||
show_demo: b8 = true
|
||||
|
||||
for !glfw.WindowShouldClose(window) {
|
||||
glfw.PollEvents()
|
||||
if glfw.GetWindowAttrib(window, glfw.ICONIFIED) != 0 {
|
||||
imgui_glfw.Sleep(10)
|
||||
continue
|
||||
}
|
||||
|
||||
imgui_gl3.NewFrame()
|
||||
imgui_glfw.NewFrame()
|
||||
imgui.NewFrame()
|
||||
|
||||
if imgui.Button("Toggle DearImgui Demo") do show_demo = !show_demo
|
||||
if show_demo do imgui.ShowDemoWindow(&show_demo)
|
||||
|
||||
_cc = clear_color.xyz
|
||||
imgui.ColorEdit3("clear color", &_cc, .None)
|
||||
imgui.SliderFloat3("clear color", &_cc, 0, 1)
|
||||
clear_color.xyz = _cc
|
||||
imgui.Render()
|
||||
|
||||
dw, dh:= glfw.GetFramebufferSize(window)
|
||||
gl.Viewport(0, 0, dw, dh)
|
||||
gl.ClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
imgui_gl3.RenderDrawData(imgui.GetDrawData());
|
||||
glfw.SwapBuffers(window);
|
||||
|
||||
}
|
||||
|
||||
imgui_gl3.Shutdown()
|
||||
imgui_glfw.Shutdown()
|
||||
imgui.DestroyContext(nil)
|
||||
|
||||
glfw.DestroyWindow(window)
|
||||
glfw.Terminate()
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user