Commit d5118cda authored by Shu's avatar Shu 🍠
Browse files

Small bits

parent d323668a
......@@ -13,12 +13,9 @@ 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.getSamples()))
if (!render::Load(window, options.preferVulkan, options.renderer, options.window))
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);
......@@ -91,6 +88,7 @@ void Client::run(server_handle* const localHandle) {
const auto actions = render::UI::Get()->draw(options, state, reports);
if (actions && render::UI::Actions::FPS) {
window.setTargetFPS(options.window.targetFPS);
pipeline->setVSync(options.window.targetFPS < Window::MIN_FPS);
}
if (actions && render::UI::Actions::FullScreen) {
window.setFullscreen(options.window.fullscreen);
......
......@@ -81,6 +81,9 @@ bool Window::create(const CreateInfo &opt) {
glfwSetWindowTitle(ptr, APP_NAME);
glfwSetWindowAttrib(ptr, GLFW_RESIZABLE, true);
setTargetFPS(opt.fps);
setFullscreen(opt.fullscreen);
return true;
}
......@@ -88,7 +91,6 @@ bool Window::isReady() const { return ptr != nullptr; }
void Window::setTargetFPS(int val) {
targetFPS = val;
glfwSwapInterval(static_cast<int>(val < MIN_FPS));
}
double Window::getTime() const {
......
......@@ -6,6 +6,13 @@
typedef struct GLFWwindow GLFWwindow;
typedef void (*GLFWframebuffersizefun)(GLFWwindow*, int, int);
struct windowOptions {
int targetFPS = 60;
int sampling = -1;
bool fullscreen = false;
constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; }
};
/// GLFW context and window
class Window {
......@@ -29,6 +36,8 @@ public:
int minor;
} client;
int samples;
int fps;
bool fullscreen;
};
bool create(const CreateInfo &opt);
void destroy();
......
......@@ -8,6 +8,7 @@
#include "render/Renderer.hpp"
#include "contouring/Abstract.hpp"
#include "control/Camera.hpp"
#include "Window.hpp"
namespace config::client {
......@@ -179,13 +180,7 @@ public:
bool controls = false;
} debugMenu;
struct {
int targetFPS = 60;
int sampling = -1;
bool fullscreen = false;
constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; }
} window;
windowOptions window;
bool preferVulkan = true;
render::renderOptions renderer;
......
......@@ -87,6 +87,7 @@ public:
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 setVSync(bool vSync) = 0;
virtual void loadUI(Window&) = 0;
......
......@@ -4,6 +4,7 @@
#include "../state.hpp"
#include "../Window.hpp"
#include "../../core/world/materials.hpp"
#include <filesystem>
using namespace render;
......@@ -16,6 +17,11 @@ UI::UI() {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::StyleColorsDark();
for(auto file: std::filesystem::directory_iterator("content/textures/")) {
if(file.is_directory() && file.path().filename() != "ui")
texturePacks.push_back(file.path().filename());
}
}
UI::~UI() {
ImGui::DestroyContext();
......@@ -115,7 +121,18 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe)) {
actions |= Actions::FillMode;
}
ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select
if (ImGui::BeginCombo("Textures", options.renderer.textures.c_str())) {
for (auto& pack: texturePacks) {
const bool is_selected = (pack == options.renderer.textures);
if (ImGui::Selectable(pack.c_str(), is_selected)) {
options.renderer.textures = pack;
actions |= Actions::RendererTextures;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
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, anisotropy.c_str())) {
......
......@@ -2,6 +2,8 @@
#include <stdint.h>
#include <cassert>
#include <vector>
#include <string>
#include "../../core/flags.hpp"
namespace config::client { struct options; }
......@@ -17,6 +19,8 @@ namespace render {
class UI {
protected:
UI();
std::vector<std::string> texturePacks;
public:
virtual ~UI();
......@@ -56,7 +60,7 @@ public:
static void Unload();
protected:
static Actions draw(config::client::options&, state::state &, const state::reports &, intptr_t aim);
Actions draw(config::client::options&, state::state &, const state::reports &, intptr_t aim);
static UI* sInstance;
};
......
......@@ -42,11 +42,14 @@ void framebuffer_size_callback(GLFWwindow *, int width, int height) {
glViewport(0, 0, width, height);
}
bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) {
Window::CreateInfo windowInfo;
windowInfo.pfnResize = framebuffer_size_callback;
windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR};
windowInfo.samples = samples;
windowInfo.samples = windOpt.getSamples();
windowInfo.fps = windOpt.targetFPS;
windowInfo.fullscreen = windOpt.fullscreen;
if (!window.create(windowInfo))
return false;
......@@ -80,6 +83,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
TracyGpuContext;
sInstance = new Renderer(opt);
sInstance->setVSync(windOpt.targetFPS < Window::MIN_FPS);
LodModel::MakeDefault();
return true;
}
......@@ -178,3 +182,7 @@ void Renderer::setClearColor(glm::vec4 c) {
void Renderer::setFillMode(bool wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);
}
void Renderer::setVSync(bool vSync) {
glfwSwapInterval(static_cast<int>(vSync));
}
\ No newline at end of file
......@@ -9,6 +9,7 @@
#include "api/Models.hpp"
#include "api/Images.hpp"
struct windowOptions;
namespace render::gl {
/// OpenGL rendering
......@@ -16,7 +17,7 @@ class Renderer final: public render::Renderer {
public:
virtual ~Renderer();
static bool Load(Window& window, const renderOptions& options, int samples);
static bool Load(Window& window, const renderOptions& options, const windowOptions& windOpt);
glm::vec3 FogColor;
GLfloat FogDepth;
......@@ -56,6 +57,7 @@ public:
void reloadShaders(const pass::VoxelProgram::options &) override;
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
void setFillMode(bool wireframe) override;
void setVSync(bool vSync) override;
void loadUI(Window &) override;
......
......@@ -5,20 +5,20 @@
namespace render {
bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples) {
bool Load(Window& window, bool preferVulkan, const renderOptions& options, const windowOptions& windOpt) {
if(!preferVulkan) {
LOG_T("Trying OpenGL");
if(gl::Renderer::Load(window, options, samples))
if(gl::Renderer::Load(window, options, windOpt))
return true;
window.destroy();
}
LOG_T("Trying Vulkan");
if(vk::Renderer::Load(window, options, samples))
if(vk::Renderer::Load(window, options, windOpt))
return true;
window.destroy();
if(preferVulkan) {
LOG_I("Fallback to OpenGL");
if(gl::Renderer::Load(window, options, samples))
if(gl::Renderer::Load(window, options, windOpt))
return true;
}
LOG_E("No available graphics library");
......
#pragma once
class Window;
struct windowOptions;
namespace render {
struct renderOptions;
bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples);
bool Load(Window& window, bool preferVulkan, const renderOptions& options, const windowOptions& windOpt);
}
\ No newline at end of file
......@@ -141,30 +141,18 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
{ // Descriptor pools
std::array<VkDescriptorPoolSize, 2> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = framebuffers.size();
poolSizes[0].descriptorCount = framebuffers.size() * 3;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = framebuffers.size() * 3;
poolSizes[1].descriptorCount = framebuffers.size() * 4;
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = framebuffers.size();
poolInfo.maxSets = framebuffers.size() * 3;
poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &voxelDescriptorPool) != VK_SUCCESS) {
FATAL("Failed to create descriptor pool!");
}
poolSizes[1].descriptorCount = framebuffers.size();
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &skyDescriptorPool) != VK_SUCCESS) {
FATAL("Failed to create descriptor pool!");
}
poolInfo.poolSizeCount = 1;
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &indicDescriptorPool) != VK_SUCCESS) {
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
FATAL("Failed to create descriptor pool!");
}
}
......@@ -172,10 +160,10 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorSetCount = framebuffers.size();
auto allocSets = [&](VkDescriptorPool pool, VkDescriptorSetLayout layout, std::vector<VkDescriptorSet>& out) {
auto allocSets = [&](VkDescriptorSetLayout layout, std::vector<VkDescriptorSet>& out) {
std::vector<VkDescriptorSetLayout> layouts(framebuffers.size(), layout);
allocInfo.descriptorPool = pool;
allocInfo.descriptorPool = descriptorPool;
allocInfo.pSetLayouts = layouts.data();
out.resize(framebuffers.size());
......@@ -183,9 +171,9 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
FATAL("Failed to allocate descriptor sets!");
}
};
allocSets(voxelDescriptorPool, pipe.getVoxelDescriptorSet(), voxelDescriptorSets);
allocSets(indicDescriptorPool, pipe.getIndicDescriptorSet(), indicDescriptorSets);
allocSets(skyDescriptorPool, pipe.getSkyDescriptorSet(), skyDescriptorSets);
allocSets(pipe.getVoxelDescriptorSet(), voxelDescriptorSets);
allocSets(pipe.getIndicDescriptorSet(), indicDescriptorSets);
allocSets(pipe.getSkyDescriptorSet(), skyDescriptorSets);
for (size_t i = 0; i < voxelDescriptorSets.size(); i++) {
VkDescriptorBufferInfo bufferInfo{};
......@@ -260,9 +248,7 @@ void CommandCenter::free() {
TracyVkDestroy(tracyCtx);
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
vkDestroyDescriptorPool(device, voxelDescriptorPool, ALLOC);
vkDestroyDescriptorPool(device, indicDescriptorPool, ALLOC);
vkDestroyDescriptorPool(device, skyDescriptorPool, ALLOC);
vkDestroyDescriptorPool(device, descriptorPool, ALLOC);
colorbuffer.reset();
depthbuffer.reset();
......
......@@ -57,17 +57,16 @@ private:
BufferGroup uniformBuffers;
VkDescriptorPool voxelDescriptorPool;
VkDescriptorPool descriptorPool;
std::vector<VkDescriptorSet> voxelDescriptorSets;
std::unique_ptr<TextureArray> voxelTextureAtlas;
std::unique_ptr<TextureArray> voxelNormalAtlas;
std::unique_ptr<TextureArray> voxelHOSAtlas;
VkDescriptorPool indicDescriptorPool;
std::vector<VkDescriptorSet> indicDescriptorSets;
std::unique_ptr<Indicator> indicCubeBuffer;
VkDescriptorPool skyDescriptorPool;
std::vector<VkDescriptorSet> skyDescriptorSets;
std::unique_ptr<TextureCube> skyboxTexture;
std::unique_ptr<Shape> skyCubeBuffer;
......
......@@ -81,7 +81,7 @@ std::optional<VkFormat> PhysicalDeviceInfo::findSupportedFormat(const std::vecto
}
VkFormat PhysicalDeviceInfo::findDepthFormat() const {
if (auto res = findSupportedFormat(
{VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
{VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT},
VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
return res.value();
......
......@@ -24,20 +24,21 @@ struct QueueFamilyIndices {
};
struct PhysicalDeviceInfo {
PhysicalDeviceInfo() {}
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface, int targetSamples):
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface, int targetSamples, bool vSync):
window(window), device(device), surface(surface),
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface))
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface)),
vSync(vSync)
{
vkGetPhysicalDeviceProperties(device, &properties);
vkGetPhysicalDeviceFeatures(device, &features);
samples = [&] {
if (targetSamples < 0)
targetSamples = 4;
VkSampleCountFlags counts = properties.limits.framebufferColorSampleCounts & properties.limits.framebufferDepthSampleCounts;
//MAYBE: properties.limits.framebufferStencilSampleCounts
if (targetSamples < 0)
targetSamples = counts / 4;
for (auto sample: {VK_SAMPLE_COUNT_64_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_16_BIT,
VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_2_BIT
VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_2_BIT
}) {
if (targetSamples >= sample && (counts & sample))
return sample;
......@@ -64,5 +65,7 @@ struct PhysicalDeviceInfo {
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceFeatures features;
std::vector<const char *> optionalExtensions;
bool vSync;
bool tripleBuffering = true;
};
}
\ No newline at end of file
......@@ -8,7 +8,7 @@
#define CONTENT_DIR "content/"
#define SHADER_DIR CONTENT_DIR "shaders/"
constexpr auto BLENDING = true;
constexpr auto BLENDING = false;
using namespace render::vk;
......
......@@ -163,11 +163,14 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugValidationCallback(VkDebugUtilsMessageSeveri
return VK_FALSE;
}
bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) {
Window::CreateInfo windowInfo;
windowInfo.pfnResize = on_resize_callback;
windowInfo.client = {Window::CreateInfo::Client::Type::VK, 0, 0};
windowInfo.samples = -1;
windowInfo.fps = windOpt.targetFPS;
windowInfo.fullscreen = windOpt.fullscreen;
if (!window.create(windowInfo))
return false;
......@@ -297,7 +300,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
uint bestScore = 0;
for(const auto& device: devices) {
uint score = 1;
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, samples);
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, windOpt.getSamples(), windOpt.targetFPS < Window::MIN_FPS);
{
uint32_t availableExtensionsCount;
......@@ -521,6 +524,12 @@ void Renderer::setFillMode(bool wireframe) {
options.wireframe = wireframe;
recreateSwapChain();
}
void Renderer::setVSync(bool vSync) {
if (vSync != getInfos().vSync) {
physicalInfo->vSync = vSync;
recreateSwapChain();
}
}
void Renderer::lookFrom(const Camera& camera) {
ProjectionMatrix = camera.getProjectionMatrix();
......
......@@ -2,6 +2,7 @@
#include "../Renderer.hpp"
#include "forward.hpp"
struct windowOptions;
namespace render::vk {
class Allocator;
class SwapChain;
......@@ -13,7 +14,7 @@ class Renderer final: public render::Renderer {
public:
virtual ~Renderer();
static bool Load(Window& window, const renderOptions& options, int samples);
static bool Load(Window& window, const renderOptions& options, const windowOptions& windOpt);
void loadUI(Window &) override;
......@@ -35,6 +36,7 @@ public:
void reloadShaders(const passOptions &) override;
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override;
void setFillMode(bool wireframe) override;
void setVSync(bool vSync) override;
Allocator* getAllocator() const { return allocator.get(); }
struct UICtx {
......
......@@ -8,13 +8,20 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue);
{ // Swapchain
VkPresentModeKHR presentMode = [&]() {
// MAYBE: add prefer no triple buffering options
for (const auto& availablePresentMode: info.swapDetails.presentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
return availablePresentMode;
std::vector<VkPresentModeKHR> preferredModes;
if (info.vSync) {
preferredModes.push_back(VK_PRESENT_MODE_FIFO_RELAXED_KHR);
} else {
if (info.tripleBuffering)
preferredModes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
preferredModes.push_back(VK_PRESENT_MODE_IMMEDIATE_KHR);
}
for(auto mode: preferredModes) {
for (const auto& availablePresentMode: info.swapDetails.presentModes) {
if (availablePresentMode == mode)
return availablePresentMode;
}
}
return VK_PRESENT_MODE_FIFO_KHR;
}();
......
......@@ -9,7 +9,7 @@ SharedUniverse::SharedUniverse(const options &o, server_handle *const localHandl
const auto id = entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{});
assert(id == PLAYER_ENTITY_ID);
localHandle->areas = (world::client::area_map*)(&areas); //FIXME: templated area
localHandle->areas = (world::client::area_map*)(&areas); //WONT FIX: templated area
localHandle->emit = std::function([&](const world::action::packet &packet) {
if(const auto fill = std::get_if<world::action::Fill>(&packet)) {
this->set(fill->pos, fill->val);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment