Vulkan ImGui full
parent
c7da6fbcc0
commit
d323668ab4
24
TODO.md
24
TODO.md
|
@ -2,11 +2,9 @@
|
|||
|
||||
## Hello screen again
|
||||
|
||||
- [~] Extract OpenGL
|
||||
- Rename Passes/Programs as Pipelines
|
||||
- [~] Minimal Vulkan
|
||||
- [ ] ImGui
|
||||
- [ ] Config (yaml)
|
||||
- [x] Extract OpenGL
|
||||
- [x] Minimal Vulkan
|
||||
- [x] ImGui
|
||||
|
||||
## Hello other
|
||||
|
||||
|
@ -16,6 +14,11 @@
|
|||
- [ ] Encryption
|
||||
- [x] Embedded
|
||||
- [x] Standalone
|
||||
- [ ] VK
|
||||
- [ ] Pipeline recreate
|
||||
- [ ] Pipeline cache
|
||||
- [ ] Reuse descriptors
|
||||
- [ ] Secondary buffers
|
||||
|
||||
## Hello world
|
||||
|
||||
|
@ -26,6 +29,7 @@
|
|||
- [~] Occlusion Culling
|
||||
- [ ] Iterator ray
|
||||
- [ ] Cast from chunk center
|
||||
- [ ] Transparency
|
||||
|
||||
## Hello darkness
|
||||
|
||||
|
@ -44,14 +48,18 @@
|
|||
- https://imgur.com/a/bh2iy
|
||||
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
|
||||
- [ ] Galaxy
|
||||
- [ ] Dynamic SIMD libs
|
||||
- [ ] FastNoiseSIMD / HastyNoise double precision
|
||||
- [ ] Octree
|
||||
- SIMD
|
||||
- [ ] Dynamic SIMD libs
|
||||
- [ ] FastNoiseSIMD / HastyNoise double precision
|
||||
- [ ] https://github.com/Auburn/FastNoise2/releases
|
||||
- [ ] Cross plateforme encoding
|
||||
- [ ] Config (yaml)
|
||||
- [ ] HDR
|
||||
- https://www.youtube.com/watch?v=iikdcAA7cww
|
||||
- Toon shading
|
||||
- Eye adaptation
|
||||
- [ ] Correct sRGB conversions
|
||||
- [ ] Post processing
|
||||
- https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing
|
||||
- Bloom
|
||||
|
@ -59,5 +67,3 @@
|
|||
- [ ] Deferred
|
||||
- [ ] Cascaded shadow maps
|
||||
- [ ] Ray Tracing
|
||||
- [ ] Transparency
|
||||
- [ ] https://github.com/Auburn/FastNoise2/releases
|
||||
|
|
|
@ -78,7 +78,6 @@ static VkDeviceSize g_BufferMemoryAlignment = 256;
|
|||
static VkPipelineCreateFlags g_PipelineCreateFlags = 0x00;
|
||||
static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;
|
||||
static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;
|
||||
static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE;
|
||||
static VkPipeline g_Pipeline = VK_NULL_HANDLE;
|
||||
|
||||
// Font data
|
||||
|
@ -179,36 +178,38 @@ layout(set=0, binding=0) uniform sampler2D sTexture;
|
|||
layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
fColor = pow(In.Color * texture(sTexture, In.UV.st), vec4(vec3(2.2), 1));
|
||||
}
|
||||
*/
|
||||
static uint32_t __glsl_shader_frag_spv[] =
|
||||
{
|
||||
0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
|
||||
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
|
||||
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
|
||||
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
|
||||
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
|
||||
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
|
||||
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
|
||||
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
|
||||
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
|
||||
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
|
||||
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
|
||||
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
|
||||
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
|
||||
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
|
||||
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
|
||||
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,
|
||||
0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,
|
||||
0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,
|
||||
0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,
|
||||
0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,
|
||||
0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd,
|
||||
0x00010038
|
||||
0x07230203,0x00010000,0x00080008,0x00000022,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
|
||||
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
|
||||
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
|
||||
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
|
||||
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
|
||||
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
|
||||
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
|
||||
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
|
||||
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
|
||||
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
|
||||
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
|
||||
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
|
||||
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
|
||||
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
|
||||
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
|
||||
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x0004002b,0x00000006,0x0000001e,
|
||||
0x400ccccd,0x0004002b,0x00000006,0x0000001f,0x3f800000,0x0007002c,0x00000007,0x00000020,
|
||||
0x0000001e,0x0000001e,0x0000001e,0x0000001f,0x00050036,0x00000002,0x00000004,0x00000000,
|
||||
0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,0x0000000f,
|
||||
0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,0x00000016,
|
||||
0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,0x0000001b,
|
||||
0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,0x00000007,
|
||||
0x0000001d,0x00000012,0x0000001c,0x0007000c,0x00000007,0x00000021,0x00000001,0x0000001a,
|
||||
0x0000001d,0x00000020,0x0003003e,0x00000009,0x00000021,0x000100fd,0x00010038
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -268,11 +269,9 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
|
|||
|
||||
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
|
||||
{
|
||||
// Bind pipeline and descriptor sets:
|
||||
// Bind pipeline:
|
||||
{
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline);
|
||||
VkDescriptorSet desc_set[1] = { g_DescriptorSet };
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);
|
||||
}
|
||||
|
||||
// Bind Vertex And Index Buffer:
|
||||
|
@ -384,6 +383,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
|||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
// Avoid rebinding textures
|
||||
ImTextureID currentTexture = nullptr;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
@ -424,6 +425,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
|||
scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y);
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
|
||||
// Bind descriptorset with font or user texture
|
||||
if (pcmd->TextureId != currentTexture) {
|
||||
VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId };
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);
|
||||
currentTexture = pcmd->TextureId;
|
||||
}
|
||||
|
||||
// Draw
|
||||
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
}
|
||||
|
@ -490,20 +498,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
|||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Update the Descriptor Set:
|
||||
{
|
||||
VkDescriptorImageInfo desc_image[1] = {};
|
||||
desc_image[0].sampler = g_FontSampler;
|
||||
desc_image[0].imageView = g_FontView;
|
||||
desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
VkWriteDescriptorSet write_desc[1] = {};
|
||||
write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write_desc[0].dstSet = g_DescriptorSet;
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].pImageInfo = desc_image;
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
|
||||
}
|
||||
VkDescriptorSet font_descriptor_set = (VkDescriptorSet)ImGui_ImplVulkan_AddTexture({g_FontSampler, g_FontView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL});
|
||||
|
||||
// Create the Upload Buffer:
|
||||
{
|
||||
|
@ -581,7 +576,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
|||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontImage;
|
||||
io.Fonts->TexID = (ImTextureID)font_descriptor_set;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -628,12 +623,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
|||
|
||||
if (!g_DescriptorSetLayout)
|
||||
{
|
||||
VkSampler sampler[1] = {g_FontSampler};
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
binding[0].pImmutableSamplers = sampler;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
|
@ -642,17 +635,6 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
|||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Create Descriptor Set:
|
||||
{
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = v->DescriptorPool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &g_DescriptorSetLayout;
|
||||
err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
if (!g_PipelineLayout)
|
||||
{
|
||||
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
|
||||
|
@ -1224,3 +1206,35 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul
|
|||
buffers->Index = 0;
|
||||
buffers->Count = 0;
|
||||
}
|
||||
|
||||
ImTextureID ImGui_ImplVulkan_AddTexture(VkDescriptorImageInfo imageInfo){
|
||||
VkResult err;
|
||||
|
||||
//TODO: hash imageInfo and cache
|
||||
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
VkDescriptorSet descriptor_set;
|
||||
// Create Descriptor Set:
|
||||
{
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = v->DescriptorPool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &g_DescriptorSetLayout;
|
||||
err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Update the Descriptor Set:
|
||||
{
|
||||
VkWriteDescriptorSet write_desc[1] = {};
|
||||
write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write_desc[0].dstSet = descriptor_set;
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].pImageInfo = &imageInfo;
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
|
||||
}
|
||||
|
||||
return (ImTextureID)descriptor_set;
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <volk.h>
|
||||
|
||||
// Initialization data, for ImGui_ImplVulkan_Init()
|
||||
// [Please zero-clear before use!]
|
||||
|
@ -50,7 +50,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, V
|
|||
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplVulkan_AddTexture(VkDescriptorImageInfo imageInfo);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
|
||||
glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
|
|
@ -1,14 +0,0 @@
|
|||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
|
||||
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||
|
||||
layout(location = 0) in struct {
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} In;
|
||||
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#version 450 core
|
||||
layout(location = 0) in vec2 aPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec4 aColor;
|
||||
|
||||
layout(push_constant) uniform uPushConstant {
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
} pc;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
layout(location = 0) out struct {
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} Out;
|
||||
|
||||
void main()
|
||||
{
|
||||
Out.Color = aColor;
|
||||
Out.UV = aUV;
|
||||
gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1);
|
||||
}
|
|
@ -1,214 +0,0 @@
|
|||
// dear imgui: standalone example application for GLFW + OpenGL 3, using programmable pipeline
|
||||
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// About Desktop OpenGL function loaders:
|
||||
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
||||
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
|
||||
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
|
||||
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
#include <GL/gl3w.h> // Initialize with gl3wInit()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
|
||||
#include <GL/glew.h> // Initialize with glewInit()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
|
||||
#include <glad/glad.h> // Initialize with gladLoadGL()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)
|
||||
#include <glad/gl.h> // Initialize with gladLoadGL(...) or gladLoaderLoadGL()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
|
||||
#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
|
||||
#include <glbinding/Binding.h> // Initialize with glbinding::Binding::initialize()
|
||||
#include <glbinding/gl/gl.h>
|
||||
using namespace gl;
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
|
||||
#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
|
||||
#include <glbinding/glbinding.h>// Initialize with glbinding::initialize()
|
||||
#include <glbinding/gl/gl.h>
|
||||
using namespace gl;
|
||||
#else
|
||||
#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
|
||||
#endif
|
||||
|
||||
// Include glfw3.h after our OpenGL definitions
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
|
||||
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
|
||||
// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
|
||||
#pragma comment(lib, "legacy_stdio_definitions")
|
||||
#endif
|
||||
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup window
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
#if __APPLE__
|
||||
// GL 3.2 + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
||||
#else
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
|
||||
#endif
|
||||
|
||||
// Create window with graphics context
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3 example", NULL, NULL);
|
||||
if (window == NULL)
|
||||
return 1;
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
|
||||
// Initialize OpenGL loader
|
||||
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
bool err = gl3wInit() != 0;
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
|
||||
bool err = glewInit() != GLEW_OK;
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
|
||||
bool err = gladLoadGL() == 0;
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)
|
||||
bool err = gladLoadGL(glfwGetProcAddress) == 0; // glad2 recommend using the windowing library loader instead of the (optionally) bundled one.
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
|
||||
bool err = false;
|
||||
glbinding::Binding::initialize();
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
|
||||
bool err = false;
|
||||
glbinding::initialize([](const char* name) { return (glbinding::ProcAddress)glfwGetProcAddress(name); });
|
||||
#else
|
||||
bool err = false; // If you use IMGUI_IMPL_OPENGL_LOADER_CUSTOM, your loader is likely to requires some form of initialization.
|
||||
#endif
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
glfwPollEvents();
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
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.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().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"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,536 +0,0 @@
|
|||
// dear imgui: standalone example application for Glfw + Vulkan
|
||||
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
|
||||
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
|
||||
// You will use those if you want to use this rendering back-end in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_vulkan.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <stdlib.h> // abort
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
|
||||
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
|
||||
// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
|
||||
#pragma comment(lib, "legacy_stdio_definitions")
|
||||
#endif
|
||||
|
||||
//#define IMGUI_UNLIMITED_FRAME_RATE
|
||||
#ifdef _DEBUG
|
||||
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||
#endif
|
||||
|
||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||
static uint32_t g_QueueFamily = (uint32_t)-1;
|
||||
static VkQueue g_Queue = VK_NULL_HANDLE;
|
||||
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
|
||||
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
||||
static int g_MinImageCount = 2;
|
||||
static bool g_SwapChainRebuild = false;
|
||||
static int g_SwapChainResizeWidth = 0;
|
||||
static int g_SwapChainResizeHeight = 0;
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
if (err == 0)
|
||||
return;
|
||||
fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
|
||||
if (err < 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||
{
|
||||
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
||||
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||
return VK_FALSE;
|
||||
}
|
||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||
|
||||
static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
// Create Vulkan Instance
|
||||
{
|
||||
VkInstanceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
create_info.enabledExtensionCount = extensions_count;
|
||||
create_info.ppEnabledExtensionNames = extensions;
|
||||
|
||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||
// Enabling multiple validation layers grouped as LunarG standard validation
|
||||
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
||||
create_info.enabledLayerCount = 1;
|
||||
create_info.ppEnabledLayerNames = layers;
|
||||
|
||||
// Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
|
||||
const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
||||
memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
|
||||
extensions_ext[extensions_count] = "VK_EXT_debug_report";
|
||||
create_info.enabledExtensionCount = extensions_count + 1;
|
||||
create_info.ppEnabledExtensionNames = extensions_ext;
|
||||
|
||||
// Create Vulkan Instance
|
||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||
check_vk_result(err);
|
||||
free(extensions_ext);
|
||||
|
||||
// Get the function pointer (required for any extensions)
|
||||
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||
IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
|
||||
|
||||
// Setup the debug report callback
|
||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
debug_report_ci.pfnCallback = debug_report;
|
||||
debug_report_ci.pUserData = NULL;
|
||||
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||
check_vk_result(err);
|
||||
#else
|
||||
// Create Vulkan Instance without any debug feature
|
||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||
check_vk_result(err);
|
||||
IM_UNUSED(g_DebugReport);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Select GPU
|
||||
{
|
||||
uint32_t gpu_count;
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||
check_vk_result(err);
|
||||
IM_ASSERT(gpu_count > 0);
|
||||
|
||||
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||
check_vk_result(err);
|
||||
|
||||
// If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
|
||||
// e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
|
||||
// for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
|
||||
g_PhysicalDevice = gpus[0];
|
||||
free(gpus);
|
||||
}
|
||||
|
||||
// Select graphics queue family
|
||||
{
|
||||
uint32_t count;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
|
||||
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
g_QueueFamily = i;
|
||||
break;
|
||||
}
|
||||
free(queues);
|
||||
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
|
||||
}
|
||||
|
||||
// Create Logical Device (with 1 queue)
|
||||
{
|
||||
int device_extension_count = 1;
|
||||
const char* device_extensions[] = { "VK_KHR_swapchain" };
|
||||
const float queue_priority[] = { 1.0f };
|
||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||
queue_info[0].queueCount = 1;
|
||||
queue_info[0].pQueuePriorities = queue_priority;
|
||||
VkDeviceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
|
||||
create_info.pQueueCreateInfos = queue_info;
|
||||
create_info.enabledExtensionCount = device_extension_count;
|
||||
create_info.ppEnabledExtensionNames = device_extensions;
|
||||
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
|
||||
check_vk_result(err);
|
||||
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||
}
|
||||
|
||||
// Create Descriptor Pool
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
|
||||
// Your real engine/app may not use them.
|
||||
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
||||
{
|
||||
wd->Surface = surface;
|
||||
|
||||
// Check for WSI support
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Select Surface Format
|
||||
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
|
||||
// Select Present Mode
|
||||
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
|
||||
#else
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
||||
#endif
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
{
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
|
||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||
// Remove the debug report callback
|
||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||
|
||||
vkDestroyDevice(g_Device, g_Allocator);
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void CleanupVulkanWindow()
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
|
||||
{
|
||||
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkResetFences(g_Device, 1, &fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = wd->RenderPass;
|
||||
info.framebuffer = fd->Framebuffer;
|
||||
info.renderArea.extent.width = wd->Width;
|
||||
info.renderArea.extent.height = wd->Height;
|
||||
info.clearValueCount = 1;
|
||||
info.pClearValues = &wd->ClearValue;
|
||||
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
// Record dear imgui primitives into command buffer
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
|
||||
|
||||
// Submit command buffer
|
||||
vkCmdEndRenderPass(fd->CommandBuffer);
|
||||
{
|
||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &image_acquired_semaphore;
|
||||
info.pWaitDstStageMask = &wait_stage;
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &fd->CommandBuffer;
|
||||
info.signalSemaphoreCount = 1;
|
||||
info.pSignalSemaphores = &render_complete_semaphore;
|
||||
|
||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &render_complete_semaphore;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
check_vk_result(err);
|
||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
|
||||
}
|
||||
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
static void glfw_resize_callback(GLFWwindow*, int w, int h)
|
||||
{
|
||||
g_SwapChainRebuild = true;
|
||||
g_SwapChainResizeWidth = w;
|
||||
g_SwapChainResizeHeight = h;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup GLFW window
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", NULL, NULL);
|
||||
|
||||
// Setup Vulkan
|
||||
if (!glfwVulkanSupported())
|
||||
{
|
||||
printf("GLFW: Vulkan Not Supported\n");
|
||||
return 1;
|
||||
}
|
||||
uint32_t extensions_count = 0;
|
||||
const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
|
||||
SetupVulkan(extensions, extensions_count);
|
||||
|
||||
// Create Window Surface
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
|
||||
check_vk_result(err);
|
||||
|
||||
// Create Framebuffers
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
ImGui_ImplGlfw_InitForVulkan(window, true);
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
init_info.Instance = g_Instance;
|
||||
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||
init_info.Device = g_Device;
|
||||
init_info.QueueFamily = g_QueueFamily;
|
||||
init_info.Queue = g_Queue;
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
// Upload Fonts
|
||||
{
|
||||
// Use any command queue
|
||||
VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
|
||||
VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
|
||||
|
||||
err = vkResetCommandPool(g_Device, command_pool, 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo begin_info = {};
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
|
||||
|
||||
VkSubmitInfo end_info = {};
|
||||
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
end_info.commandBufferCount = 1;
|
||||
end_info.pCommandBuffers = &command_buffer;
|
||||
err = vkEndCommandBuffer(command_buffer);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
}
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
glfwPollEvents();
|
||||
|
||||
// Resize swap chain?
|
||||
if (g_SwapChainRebuild && g_SwapChainResizeWidth > 0 && g_SwapChainResizeHeight > 0)
|
||||
{
|
||||
g_SwapChainRebuild = false;
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
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.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().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"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
|
||||
if (!is_minimized)
|
||||
{
|
||||
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
||||
FrameRender(wd, draw_data);
|
||||
FramePresent(wd);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow();
|
||||
CleanupVulkan();
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -13,15 +13,16 @@ Client::Client(config::client::options& options): options(options) { }
|
|||
Client::~Client() { }
|
||||
|
||||
void Client::run(server_handle* const localHandle) {
|
||||
if (!render::Load(window, options.preferVulkan, options.renderer, options.window.samples))
|
||||
if (!render::Load(window, options.preferVulkan, options.renderer, options.window.getSamples()))
|
||||
return;
|
||||
|
||||
window.setTargetFPS(options.window.targetFPS);
|
||||
|
||||
window.setFullscreen(options.window.fullscreen);
|
||||
|
||||
InputMap inputs(window.getPtr());
|
||||
Controllable player(window.getPtr(), inputs, options.control);
|
||||
Camera camera(&player, options.camera);
|
||||
state.position = player.position;
|
||||
|
||||
auto pipeline = render::Renderer::Get();
|
||||
pipeline->LightInvDir = glm::normalize(glm::vec3(-.5f, 2, -2));
|
||||
|
@ -55,7 +56,7 @@ void Client::run(server_handle* const localHandle) {
|
|||
}
|
||||
camera.update();
|
||||
pipeline->lookFrom(camera);
|
||||
pipeline->LightInvDir = glm::vec3(glm::rotate(glm::mat4(1), deltaTime * .5f, glm::vec3(1, .5, .1)) * glm::vec4(pipeline->LightInvDir, 0));
|
||||
pipeline->LightInvDir = glm::vec3(glm::rotate(glm::mat4(1), deltaTime * .1f, glm::vec3(1, .5, .1)) * glm::vec4(pipeline->LightInvDir, 0));
|
||||
|
||||
{
|
||||
const auto ray_result = world->raycast(camera.getRay() * options.voxel_density);
|
||||
|
@ -113,7 +114,7 @@ void Client::run(server_handle* const localHandle) {
|
|||
player.setOptions(options.control);
|
||||
}
|
||||
if(actions && render::UI::Actions::FillMode) {
|
||||
//TODO: pipeline->setFillMode(options.renderer.wireframe);
|
||||
pipeline->setFillMode(options.renderer.wireframe);
|
||||
}
|
||||
}
|
||||
{ // Rendering
|
||||
|
@ -184,7 +185,6 @@ void Client::run(server_handle* const localHandle) {
|
|||
options.contouring = state.contouring->getOptions();
|
||||
world.reset();
|
||||
|
||||
render::UI::Unload();
|
||||
render::Renderer::Unload();
|
||||
window.destroy();
|
||||
}
|
|
@ -43,7 +43,6 @@ bool Window::create(const CreateInfo &opt) {
|
|||
break;
|
||||
|
||||
case CreateInfo::Client::Type::VK:
|
||||
LOG_W("WIP client type");
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
break;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
assert(config["enabled"]);
|
||||
|
||||
window.targetFPS = config["window"]["target_fps"].value_or(window.targetFPS);
|
||||
window.samples = config["window"]["samples"].value_or(window.samples);
|
||||
window.sampling = config["window"]["sampling"].value_or(window.sampling);
|
||||
window.fullscreen = config["window"]["fullscreen"].value_or(window.fullscreen);
|
||||
renderer.inFlightFrames = config["window"]["parallel_frames"].value_or(renderer.inFlightFrames);
|
||||
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
config.insert_or_assign("enabled", true);
|
||||
config.insert_or_assign("window", toml::table({
|
||||
{"target_fps", window.targetFPS},
|
||||
{"samples", window.samples},
|
||||
{"sampling", window.sampling},
|
||||
{"fullscreen", window.fullscreen},
|
||||
{"parallel_frames", renderer.inFlightFrames}
|
||||
}));
|
||||
|
@ -181,8 +181,10 @@ public:
|
|||
|
||||
struct {
|
||||
int targetFPS = 60;
|
||||
int samples = -1;
|
||||
int sampling = -1;
|
||||
bool fullscreen = false;
|
||||
|
||||
constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; }
|
||||
} window;
|
||||
|
||||
bool preferVulkan = true;
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
virtual void setClearColor(glm::vec4) = 0;
|
||||
virtual void reloadShaders(const passOptions &) = 0;
|
||||
virtual void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) = 0;
|
||||
virtual void setFillMode(bool wireframe) = 0;
|
||||
|
||||
virtual void loadUI(Window&) = 0;
|
||||
|
||||
|
|
|
@ -52,14 +52,24 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
|||
|
||||
if (options.debugMenu.render) {
|
||||
ImGui::Begin("Debug: Render", &options.debugMenu.render, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImGui::Text("Tris: %ld (%ld models)", reports.tris_count, reports.models_count);
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Overlay", &options.overlay.visible);
|
||||
{
|
||||
ImGui::Combo("Driver", (int*)&options.preferVulkan, "OpenGL\0Vulkan\0");
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Prefer Vulkan over OpenGL if available (requires restart)");
|
||||
auto samples = std::to_string(options.window.getSamples()) + "x";
|
||||
ImGui::SliderInt("MSAA", &options.window.sampling, -1, 7, options.window.sampling > 0 ? samples.c_str() :
|
||||
(options.window.sampling < 0 ? "System default" : "Minimun"));
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Anti-aliasing (requires restart).\nActual value may be smaller than requested");
|
||||
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("FPS", &options.window.targetFPS, Window::MIN_FPS-1, Window::MAX_FPS+1, options.window.targetFPS > Window::MIN_FPS ? (options.window.targetFPS < Window::MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
|
||||
actions |= Actions::FPS;
|
||||
}
|
||||
|
||||
ImGui::Text("Sampling %d (requires restart)", options.window.samples);
|
||||
if (ImGui::Checkbox("Fullscreen", &options.window.fullscreen)){
|
||||
actions |= Actions::FullScreen;
|
||||
}
|
||||
|
@ -106,8 +116,9 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
|||
actions |= Actions::FillMode;
|
||||
}
|
||||
ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select
|
||||
std::string anisotropy = std::to_string(options.renderer.getAnisotropy()) + "x";
|
||||
if (ImGui::SliderInt("Quality", &options.renderer.textureQuality, 0, 200, "%d%%") |
|
||||
ImGui::SliderInt("Sharpness", &options.renderer.textureSharpness, 0, 8)) {
|
||||
ImGui::SliderInt("Sharpness", &options.renderer.textureSharpness, 0, 8, anisotropy.c_str())) {
|
||||
actions |= Actions::RendererTextures;
|
||||
}
|
||||
if(ImGui::IsItemHovered())
|
||||
|
|
|
@ -29,9 +29,11 @@ Renderer::Renderer(const renderOptions& options):
|
|||
|
||||
FogColor = glm::vec3(options.clear_color.x, options.clear_color.y, options.clear_color.z);
|
||||
loadTextures(options.textures, options.getMipmapLodBias(), options.getAnisotropy());
|
||||
setFillMode(options.wireframe);
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
render::UI::Unload();
|
||||
unloadTextures();
|
||||
glDeleteVertexArrays(1, &VertexArrayID);
|
||||
}
|
||||
|
@ -172,3 +174,7 @@ void Renderer::setClearColor(glm::vec4 c) {
|
|||
FogColor = c;
|
||||
glClearColor(c.r, c.g, c.b, c.a);
|
||||
}
|
||||
|
||||
void Renderer::setFillMode(bool wireframe) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
void lookFrom(const Camera&) override;
|
||||
void reloadShaders(const pass::VoxelProgram::options &) override;
|
||||
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
|
||||
void setFillMode(bool wireframe) override;
|
||||
|
||||
void loadUI(Window &) override;
|
||||
|
||||
|
|
|
@ -175,6 +175,11 @@ void submitCmd(VkCommandBuffer buffer, VkQueue queue) {
|
|||
vkQueueWaitIdle(queue); //MAYBE: use fences
|
||||
vkResetCommandBuffer(buffer, 0);
|
||||
}
|
||||
void Allocator::transfer(std::function<void(VkCommandBuffer)> call) {
|
||||
beginCmd(transferBuffer);
|
||||
call(transferBuffer);
|
||||
submitCmd(transferBuffer, transferQueue);
|
||||
}
|
||||
void Allocator::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) {
|
||||
beginCmd(transferBuffer);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
namespace render::vk {
|
||||
|
||||
|
@ -32,6 +33,7 @@ public:
|
|||
memory::ptr allocate(VkMemoryRequirements, VkMemoryPropertyFlags, bool optimalTiling = false);
|
||||
bool deallocate(const memory::area&);
|
||||
|
||||
void transfer(std::function<void(VkCommandBuffer)>);
|
||||
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, uint32_t arrayLayers);
|
||||
void copyBufferToImage(VkBuffer src, VkImage dst, uint32_t width, uint32_t height, uint32_t mipLevels = 1, uint32_t arrayLayer = 0);
|
||||
|
|
|
@ -113,6 +113,23 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
|||
}
|
||||
}
|
||||
|
||||
uiFramebuffers.resize(views.size());
|
||||
|
||||
for (size_t i = 0; i < views.size(); i++) {
|
||||
VkFramebufferCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
info.renderPass = pipe.getUIRenderPass();
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &views[i];
|
||||
info.width = extent.width;
|
||||
info.height = extent.height;
|
||||
info.layers = 1;
|
||||
|
||||
if (vkCreateFramebuffer(device, &info, ALLOC, &uiFramebuffers[i]) != VK_SUCCESS) {
|
||||
FATAL("Failed to create ui framebuffer!");
|
||||
}
|
||||
}
|
||||
|
||||
{ // Uniform buffers
|
||||
std::vector<Buffer::requirement> requirements;
|
||||
requirements.resize(framebuffers.size(), Buffer::requirement(sizeof(VoxelUBO), Buffer::Usage::UNIFORM));
|
||||
|
@ -253,6 +270,9 @@ void CommandCenter::free() {
|
|||
for (size_t i = 0; i < framebuffers.size(); i++) {
|
||||
vkDestroyFramebuffer(device, framebuffers[i], ALLOC);
|
||||
}
|
||||
for (size_t i = 0; i < uiFramebuffers.size(); i++) {
|
||||
vkDestroyFramebuffer(device, uiFramebuffers[i], ALLOC);
|
||||
}
|
||||
|
||||
freed = true;
|
||||
}
|
||||
|
@ -277,7 +297,7 @@ void CommandCenter::startRecording(uint32_t idx, VkRenderPass renderPass, VkExte
|
|||
if (!idx) {
|
||||
TracyVkCollect(tracyCtx, graphicsBuffers[idx]);
|
||||
}
|
||||
TracyVkZone(tracyCtx, graphicsBuffers[idx], "Render");
|
||||
TracyVkZone(tracyCtx, graphicsBuffers[idx], "Begin");
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = renderPass;
|
||||
|
@ -336,9 +356,24 @@ void CommandCenter::recordPostprocess(uint32_t idx, const Subpass& skyPass, bool
|
|||
vkCmdDraw(graphicsBuffers[idx], skyCubeBuffer->size, 1, 0, 0);
|
||||
}
|
||||
vkCmdEndRenderPass(graphicsBuffers[idx]);
|
||||
TracyVkZone(tracyCtx, graphicsBuffers[idx], "Swap");
|
||||
}
|
||||
void CommandCenter::recordUI(uint32_t idx, VkRenderPass uiPass, VkExtent2D extent, const std::function<void(VkCommandBuffer)>& call) {
|
||||
TracyVkZone(tracyCtx, graphicsBuffers[idx], "UI");
|
||||
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = uiPass;
|
||||
info.framebuffer = uiFramebuffers[idx];
|
||||
info.renderArea.extent = extent;
|
||||
info.clearValueCount = 1;
|
||||
VkClearValue clearValue{};
|
||||
clearValue.color = {0.f, 0.f, 0.f, 1.f};
|
||||
info.pClearValues = &clearValue;
|
||||
vkCmdBeginRenderPass(graphicsBuffers[idx], &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
call(graphicsBuffers[idx]);
|
||||
vkCmdEndRenderPass(graphicsBuffers[idx]);
|
||||
}
|
||||
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
||||
assert(!freed);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "forward.hpp"
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include "api/Buffers.hpp"
|
||||
#include "api/Images.hpp"
|
||||
|
@ -29,17 +30,19 @@ public:
|
|||
void startIndicPass(uint32_t idx, const Subpass&);
|
||||
size_t recordIndicator(uint32_t idx, const Subpass&, glm::mat4 model);
|
||||
void recordPostprocess(uint32_t idx, const Subpass&, bool skybox);
|
||||
void recordUI(uint32_t idx, VkRenderPass uiPass, VkExtent2D, const std::function<void(VkCommandBuffer)> &);
|
||||
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
||||
|
||||
void loadAtlases(const std::string &texturePath, int anisotropy, float lodBias);
|
||||
void allocate(const std::vector<VkImageView>&, const Pipeline&, VkPhysicalDevice, VkExtent2D);
|
||||
void free();
|
||||
|
||||
private:
|
||||
void loadAtlases(const std::string &texturePath, int anisotropy, float lodBias);
|
||||
|
||||
VkDevice device;
|
||||
|
||||
std::vector<VkFramebuffer> framebuffers;
|
||||
std::vector<VkFramebuffer> uiFramebuffers;
|
||||
|
||||
VkFormat colorFormat;
|
||||
VkSampleCountFlagBits colorSamples;
|
||||
|
|
|
@ -23,8 +23,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
colorAttachment.finalLayout = hasSamples ?
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
// NOTE: UI RenderPass do VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
||||
|
||||
VkAttachmentReference colorAttachmentRef{};
|
||||
colorAttachmentRef.attachment = 0; //TODO: layouts bind
|
||||
|
@ -52,7 +52,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
// NOTE: UI RenderPass do VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
||||
|
||||
VkAttachmentReference colorAttachmentResolveRef{};
|
||||
colorAttachmentResolveRef.attachment = 2;
|
||||
|
@ -126,6 +127,46 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
FATAL("Failed to create render pass!");
|
||||
}
|
||||
}
|
||||
{ // UI Render pass
|
||||
VkAttachmentDescription attachment = {};
|
||||
attachment.format = info.getSurfaceFormat().format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
VkAttachmentReference color_attachment = {};
|
||||
color_attachment.attachment = 0;
|
||||
color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_attachment;
|
||||
|
||||
VkSubpassDependency dependency = {};
|
||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
dependency.dstSubpass = 0;
|
||||
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dependency.srcAccessMask = 0; // or VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
VkRenderPassCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &attachment;
|
||||
info.subpassCount = 1;
|
||||
info.pSubpasses = &subpass;
|
||||
info.dependencyCount = 1;
|
||||
info.pDependencies = &dependency;
|
||||
if (vkCreateRenderPass(device, &info, nullptr, &uiRenderPass) != VK_SUCCESS) {
|
||||
FATAL("Failed to create UI render pass!");
|
||||
}
|
||||
}
|
||||
//MAYBE: use sets (ubo, (samplers, passInfos))
|
||||
//MAYBE: reuse sub UBO
|
||||
{ // Voxel descriptor
|
||||
|
@ -310,7 +351,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizer.depthClampEnable = VK_FALSE;
|
||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||
rasterizer.polygonMode = options.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
||||
rasterizer.polygonMode = options.wireframe && info.features.fillModeNonSolid ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
||||
rasterizer.lineWidth = 1.0f;
|
||||
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
|
@ -519,6 +560,8 @@ Pipeline::~Pipeline() {
|
|||
vkDestroyPipelineLayout(device, pass.layout, ALLOC);
|
||||
};
|
||||
|
||||
vkDestroyRenderPass(device, uiRenderPass, ALLOC);
|
||||
|
||||
destroy(worldPass);
|
||||
destroy(indicPass);
|
||||
destroy(skyPass);
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
constexpr VkDescriptorSetLayout getSkyDescriptorSet() const { return skyDescriptorSet; }
|
||||
constexpr const Subpass& getSkyPass() const { return skyPass; }
|
||||
|
||||
constexpr VkRenderPass getUIRenderPass() const { return uiRenderPass; }
|
||||
|
||||
private:
|
||||
VkDevice device;
|
||||
|
||||
|
@ -40,5 +42,7 @@ private:
|
|||
Subpass worldPass;
|
||||
Subpass indicPass;
|
||||
Subpass skyPass;
|
||||
|
||||
VkRenderPass uiRenderPass;
|
||||
};
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <Tracy.hpp>
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
|
@ -81,6 +82,7 @@ Renderer::~Renderer() {
|
|||
vkDeviceWaitIdle(device);
|
||||
const auto imageCount = swapChain->getImageViews().size();
|
||||
destroySwapChain();
|
||||
render::UI::Unload();
|
||||
|
||||
for(size_t i = 0; i < renderFinishedSemaphores.size(); i++) {
|
||||
vkDestroyFence(device, inFlightFences[i], ALLOC);
|
||||
|
@ -111,6 +113,8 @@ void Renderer::recreateSwapChain() {
|
|||
swapChain = std::make_unique<SwapChain>(device, getInfos());
|
||||
pipeline = std::make_unique<Pipeline>(device, getInfos(), options);
|
||||
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().device, getInfos().swapDetails.capabilities.currentExtent);
|
||||
|
||||
dynamic_cast<UI*>(UI::Get())->setImageCount(swapChain->getImageViews().size());
|
||||
}
|
||||
void Renderer::destroySwapChain() {
|
||||
commandCenter->free();
|
||||
|
@ -333,6 +337,12 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
|
|||
if (infos.features.samplerAnisotropy)
|
||||
score += 1000;
|
||||
|
||||
if (infos.features.sampleRateShading)
|
||||
score += 1500;
|
||||
|
||||
if (infos.features.fillModeNonSolid)
|
||||
score += 100;
|
||||
|
||||
//TODO: check others limits
|
||||
|
||||
if (!infos.queueIndices.isComplete())
|
||||
|
@ -377,6 +387,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
|
|||
deviceFeatures.geometryShader = physicalInfo.features.geometryShader;
|
||||
deviceFeatures.samplerAnisotropy = physicalInfo.features.samplerAnisotropy;
|
||||
deviceFeatures.sampleRateShading = physicalInfo.features.sampleRateShading;
|
||||
deviceFeatures.fillModeNonSolid = physicalInfo.features.fillModeNonSolid;
|
||||
|
||||
std::vector<const char*> extensions(requiredExtensions);
|
||||
extensions.insert(extensions.end(), physicalInfo.optionalExtensions.begin(), physicalInfo.optionalExtensions.end());
|
||||
|
@ -404,6 +415,12 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
|
|||
LodModel::MakeDefault();
|
||||
return true;
|
||||
}
|
||||
Renderer::UICtx Renderer::getUICtx() const {
|
||||
auto queueFamily = physicalInfo->queueIndices.graphicsFamily.value();
|
||||
VkQueue queue;
|
||||
vkGetDeviceQueue(device, queueFamily, 0, &queue);
|
||||
return {instance, physicalInfo->device, device, queueFamily, queue, (uint32_t)swapChain->getImageViews().size(), pipeline->getUIRenderPass()};
|
||||
}
|
||||
|
||||
void Renderer::loadUI(Window& w) {
|
||||
UI::Load(w);
|
||||
|
@ -411,6 +428,7 @@ void Renderer::loadUI(Window& w) {
|
|||
|
||||
void Renderer::beginFrame() {
|
||||
assert(currentImage == UINT32_MAX);
|
||||
ZoneScopedN("VkWaitForFrame");
|
||||
|
||||
if (auto newImage = swapChain->acquireNextImage(imageAvailableSemaphores[currentFrame], inFlightFences[currentFrame])) {
|
||||
currentImage = newImage.value();
|
||||
|
@ -467,7 +485,10 @@ std::function<size_t(glm::mat4)> Renderer::beginIndicatorPass() {
|
|||
void Renderer::postProcess() {
|
||||
commandCenter->recordPostprocess(currentImage, pipeline->getSkyPass(), options.skybox);
|
||||
}
|
||||
|
||||
void Renderer::recordUI(std::function<void(VkCommandBuffer)> call) {
|
||||
return commandCenter->recordUI(currentImage, pipeline->getUIRenderPass(),
|
||||
getInfos().swapDetails.capabilities.currentExtent, call);
|
||||
}
|
||||
void Renderer::endFrame() {
|
||||
commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame],
|
||||
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
||||
|
@ -485,13 +506,20 @@ void Renderer::swapBuffer(Window&) {
|
|||
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||
}
|
||||
|
||||
void Renderer::reloadShaders(const passOptions&) {
|
||||
/*WorldPass = std::make_unique<pass::WorldProgram>(options);
|
||||
EntityPass = std::make_unique<pass::EntityProgram>(options);*/
|
||||
void Renderer::reloadShaders(const passOptions& opt) {
|
||||
options.voxel = opt;
|
||||
recreateSwapChain();
|
||||
}
|
||||
void Renderer::reloadTextures(const std::string&, float, float) {
|
||||
/*unloadTextures();
|
||||
loadTextures(texturePath, mipMapLOD, anisotropy);*/
|
||||
void Renderer::reloadTextures(const std::string& textures, float mipmap, float anisotropy) {
|
||||
vkDeviceWaitIdle(device);
|
||||
commandCenter->free();
|
||||
commandCenter->loadAtlases(textures, anisotropy, mipmap);
|
||||
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().device,
|
||||
getInfos().swapDetails.capabilities.currentExtent);
|
||||
}
|
||||
void Renderer::setFillMode(bool wireframe) {
|
||||
options.wireframe = wireframe;
|
||||
recreateSwapChain();
|
||||
}
|
||||
|
||||
void Renderer::lookFrom(const Camera& camera) {
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() override;
|
||||
std::function<size_t(glm::mat4)> beginIndicatorPass() override;
|
||||
void postProcess() override;
|
||||
void recordUI(std::function<void(VkCommandBuffer)>);
|
||||
void endFrame() override;
|
||||
void swapBuffer(Window &) override;
|
||||
|
||||
|
@ -33,8 +34,19 @@ public:
|
|||
void lookFrom(const Camera &) override;
|
||||
void reloadShaders(const passOptions &) override;
|
||||
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
|
||||
void setFillMode(bool wireframe) override;
|
||||
|
||||
Allocator* getAllocator() const { return allocator.get(); }
|
||||
struct UICtx {
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkDevice device;
|
||||
uint32_t queueFamily;
|
||||
VkQueue queue;
|
||||
uint32_t imageCount;
|
||||
VkRenderPass renderPass;
|
||||
};
|
||||
UICtx getUICtx() const;
|
||||
|
||||
void setResized() { framebufferResized = true; }
|
||||
|
||||
|
|
|
@ -1,28 +1,103 @@
|
|||
#include "UI.hpp"
|
||||
|
||||
#include "../../Window.hpp"
|
||||
#include <GL/gl3w.h>
|
||||
#include "Renderer.hpp"
|
||||
#include "Allocator.hpp"
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_vulkan.h>
|
||||
#include "../../../core/utils/logger.hpp"
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
static void imgui_check_vk_result(VkResult err) {
|
||||
if (err == 0)
|
||||
return;
|
||||
if (err < 0) {
|
||||
FATAL("VK ImGui error " << err);
|
||||
} else {
|
||||
LOG_W("VK ImGui error " << err);
|
||||
}
|
||||
}
|
||||
|
||||
UI::UI(GLFWwindow *window): render::UI() {
|
||||
auto ctx = Renderer::Get()->getUICtx();
|
||||
device = ctx.device;
|
||||
{ // Descriptor pool
|
||||
std::array<VkDescriptorPoolSize, 11> poolSizes{};
|
||||
poolSizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
poolSizes[0].descriptorCount = 1000;
|
||||
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
poolSizes[1].descriptorCount = 1000;
|
||||
poolSizes[2].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
poolSizes[2].descriptorCount = 1000;
|
||||
poolSizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
poolSizes[3].descriptorCount = 1000;
|
||||
poolSizes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
poolSizes[4].descriptorCount = 1000;
|
||||
poolSizes[5].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||
poolSizes[5].descriptorCount = 1000;
|
||||
poolSizes[6].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSizes[6].descriptorCount = 1000;
|
||||
poolSizes[7].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
poolSizes[7].descriptorCount = 1000;
|
||||
poolSizes[8].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||
poolSizes[8].descriptorCount = 1000;
|
||||
poolSizes[9].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
||||
poolSizes[9].descriptorCount = 1000;
|
||||
poolSizes[10].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
poolSizes[10].descriptorCount = 1000;
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
poolInfo.poolSizeCount = poolSizes.size();
|
||||
poolInfo.pPoolSizes = poolSizes.data();
|
||||
poolInfo.maxSets = 1000 * poolSizes.size();
|
||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
|
||||
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
|
||||
FATAL("Failed to create UI descriptor pool!");
|
||||
}
|
||||
}
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
/*ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
aim = Texture::CreatePtr("ui/Aim", false);*/
|
||||
ImGui_ImplGlfw_InitForVulkan(window, true);
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
init_info.Instance = ctx.instance;
|
||||
init_info.PhysicalDevice = ctx.physicalDevice;
|
||||
init_info.Device = ctx.device;
|
||||
init_info.QueueFamily = ctx.queueFamily;
|
||||
init_info.Queue = ctx.queue;
|
||||
init_info.PipelineCache = VK_NULL_HANDLE;
|
||||
init_info.DescriptorPool = descriptorPool;
|
||||
init_info.Allocator = nullptr;
|
||||
init_info.MinImageCount = ctx.imageCount;
|
||||
init_info.ImageCount = ctx.imageCount;
|
||||
init_info.CheckVkResultFn = imgui_check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info, ctx.renderPass);
|
||||
Allocator::GetDefault()->transfer(ImGui_ImplVulkan_CreateFontsTexture);
|
||||
aimTexture = Texture::LoadFromFile("content/textures/ui/Aim.dds", {false, false, Texture::Wrap::MIRRORED_REPEAT, 0, false});
|
||||
aimHandle = (intptr_t)ImGui_ImplVulkan_AddTexture(aimTexture->getDescriptor());
|
||||
}
|
||||
UI::~UI() {
|
||||
/*ImGui_ImplGlfw_Shutdown();
|
||||
ImGui_ImplOpenGL3_Shutdown();*/
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
|
||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||
}
|
||||
|
||||
void UI::setImageCount(uint32_t count) {
|
||||
ImGui_ImplVulkan_SetMinImageCount(count);
|
||||
}
|
||||
|
||||
UI::Actions UI::draw(config::client::options &o, state::state &s, const state::reports &r) {
|
||||
/*ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();*/
|
||||
return UI::Actions::None; //render::UI::draw(o, s, r, aim);
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
return render::UI::draw(o, s, r, aimHandle);
|
||||
}
|
||||
void UI::render() {
|
||||
//ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
Renderer::Get()->recordUI([](VkCommandBuffer buffer){
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), buffer);
|
||||
});
|
||||
}
|
||||
|
||||
void UI::Load(Window& w) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "../UI.hpp"
|
||||
#include "forward.hpp"
|
||||
#include "api/Images.hpp"
|
||||
struct GLFWwindow;
|
||||
class Window;
|
||||
|
||||
|
@ -18,7 +20,13 @@ public:
|
|||
Actions draw(config::client::options &, state::state &, const state::reports &) override;
|
||||
void render() override;
|
||||
|
||||
void setImageCount(uint32_t);
|
||||
|
||||
private:
|
||||
intptr_t aim;
|
||||
VkDevice device;
|
||||
|
||||
std::unique_ptr<Texture> aimTexture;
|
||||
intptr_t aimHandle;
|
||||
VkDescriptorPool descriptorPool;
|
||||
};
|
||||
}
|
|
@ -82,6 +82,7 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
|
|||
switch (type) {
|
||||
case server_packet_type::CAPABILITIES: {
|
||||
PacketReader(packet).read(serverDistance);
|
||||
emit(world::action::Move(pos));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ LocalUniverse::~LocalUniverse() {
|
|||
void LocalUniverse::update(voxel_pos pos, float) {
|
||||
const auto cur_chunk = glm::divide(pos);
|
||||
const auto chunkChange = cur_chunk != last_chunk;
|
||||
if (last_chunk.x == INT_MAX)
|
||||
emit(world::action::Move(pos));
|
||||
last_chunk = cur_chunk;
|
||||
|
||||
if(chunkChange) {
|
||||
|
|
Loading…
Reference in New Issue