Vulkan MSAA
This commit is contained in:
parent
9465083742
commit
7f6136bffd
75
README.md
75
README.md
|
@ -6,12 +6,14 @@ Work in progress galaxy down to atom (mostly centimeter) online voxel game
|
||||||
|
|
||||||
- [About The Project](#about-the-project)
|
- [About The Project](#about-the-project)
|
||||||
- [Built With](#built-with)
|
- [Built With](#built-with)
|
||||||
- [Getting Started](#getting-started)
|
- [Run it](#run-it)
|
||||||
- [Prerequisites](#prerequisites)
|
- [Prerequisites](#prerequisites)
|
||||||
- [Build](#build)
|
- [Usage](#usage)
|
||||||
|
- [Build](#build)
|
||||||
|
- [Prerequisites](#prerequisites-1)
|
||||||
- [Optionally](#optionally)
|
- [Optionally](#optionally)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Usage](#usage)
|
- [Additionally](#additionally)
|
||||||
- [RoadMap](#roadmap)
|
- [RoadMap](#roadmap)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
- [Contact](#contact)
|
- [Contact](#contact)
|
||||||
|
@ -35,16 +37,30 @@ Experimental project using OpenGL and Vulkan.
|
||||||
|
|
||||||
|
|
||||||
<!-- GETTING STARTED -->
|
<!-- GETTING STARTED -->
|
||||||
## Getting Started
|
## Run it
|
||||||
|
|
||||||
To get a local copy up and running, follow these simple steps.
|
|
||||||
|
|
||||||
|
Get a release compatible with your system window library and processor capabilities, or [build](#build) it
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* OpenGL or Vulkan driver
|
* OpenGL or Vulkan driver
|
||||||
|
|
||||||
#### Build
|
### Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./univerxel
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `config.toml`
|
||||||
|
<!-- MAYBE: config description -->
|
||||||
|
|
||||||
|
Profit !
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
To get a local copy up and running, follow these simple steps.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
* C++17
|
* C++17
|
||||||
* CMake 3.11
|
* CMake 3.11
|
||||||
|
@ -53,8 +69,9 @@ To get a local copy up and running, follow these simple steps.
|
||||||
#### Optionally
|
#### Optionally
|
||||||
|
|
||||||
* Python: utility scripts
|
* Python: utility scripts
|
||||||
* Tracy v0.7: profiling
|
* [Tracy](https://github.com/wolfpld/tracy) v0.7: profiling
|
||||||
* glslc: compile vk shaders
|
* [glslc](https://github.com/KhronosGroup/glslang): build vk shaders
|
||||||
|
* [Compressonator](https://github.com/GPUOpen-Tools/compressonator): build textures
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
|
@ -68,23 +85,47 @@ mkdir build && cd build
|
||||||
```
|
```
|
||||||
3. Build CMake
|
3. Build CMake
|
||||||
```sh
|
```sh
|
||||||
cmake ..
|
cmake <options> ..
|
||||||
```
|
```
|
||||||
4. Build Make
|
|
||||||
|
CMake options: `-DKEY=VAL`
|
||||||
|
Key | Usage | Default
|
||||||
|
--- | --- | ---
|
||||||
|
SIMD_LEVEL | SIMD processor acceleration (sse2, sse4.1, avx2, avx512f) | `avx2`
|
||||||
|
USE_FMA | Fast math | `1`
|
||||||
|
CMAKE_BUILD_TYPE | Level of optimization | `Release`
|
||||||
|
PROFILING | Tracy profiling | `0`
|
||||||
|
LOG_DEBUG | Debug logs | `0`
|
||||||
|
LOG_TRACE | Trace logs | `0`
|
||||||
|
|
||||||
|
1. Build Make
|
||||||
```sh
|
```sh
|
||||||
make
|
make -j<process count> <target>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Target | Description
|
||||||
|
--- | ---
|
||||||
|
univerxel | All in one
|
||||||
|
univerxel-server | Standalone server
|
||||||
|
univerxel-client | Light client
|
||||||
|
docs | Doxygen documentation
|
||||||
|
|
||||||
<!-- USAGE EXAMPLES -->
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
|
#### Additionally
|
||||||
|
|
||||||
|
5. Recompile Vulkan shaders
|
||||||
```sh
|
```sh
|
||||||
./univerxel
|
cd resource/shaders-src
|
||||||
|
./compile.sh # Use glslc
|
||||||
|
GLSL="glslValidator -V" ./compile.sh # Other glslang compiler
|
||||||
```
|
```
|
||||||
|
|
||||||
Profit !
|
6. Rebuild textures
|
||||||
|
```sh
|
||||||
|
cd resource/textures-src
|
||||||
|
./merge <args> # combine grey images to RGBA
|
||||||
|
Compressonator -fd BC3 -mipsize <size> <in> <out>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
<!-- ROADMAP -->
|
<!-- ROADMAP -->
|
||||||
|
|
BIN
resource/content/textures/1024-realistic/terrain/Mapl.dds (Stored with Git LFS)
BIN
resource/content/textures/1024-realistic/terrain/Mapl.dds (Stored with Git LFS)
Binary file not shown.
|
@ -13,7 +13,7 @@ Client::Client(config::client::options& options): options(options) { }
|
||||||
Client::~Client() { }
|
Client::~Client() { }
|
||||||
|
|
||||||
void Client::run(server_handle* const localHandle) {
|
void Client::run(server_handle* const localHandle) {
|
||||||
if (!render::Load(window, options.preferVulkan, options.renderer))
|
if (!render::Load(window, options.preferVulkan, options.renderer, options.window.samples))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window.setTargetFPS(options.window.targetFPS);
|
window.setTargetFPS(options.window.targetFPS);
|
||||||
|
|
|
@ -72,11 +72,16 @@ public:
|
||||||
};
|
};
|
||||||
struct requirement: properties {
|
struct requirement: properties {
|
||||||
requirement(const properties& props, Layout layout, Usage usage, Aspect aspect,
|
requirement(const properties& props, Layout layout, Usage usage, Aspect aspect,
|
||||||
bool optimal = true): properties(props), layout(layout), usage(usage),
|
int samples = 1, bool optimal = true): properties(props), layout(layout),
|
||||||
aspect(aspect), optimal(optimal) { }
|
usage(usage), aspect(aspect), samples(samples), optimal(optimal)
|
||||||
|
{
|
||||||
|
assert(samples > 0 && (ceil(log2(n)) == floor(log2(n))) && "Samples must be pow2");
|
||||||
|
}
|
||||||
Layout layout;
|
Layout layout;
|
||||||
Usage usage;
|
Usage usage;
|
||||||
Aspect aspect;
|
Aspect aspect;
|
||||||
|
//NOTE: matches VkSampleCountFlagBits
|
||||||
|
int samples;
|
||||||
bool optimal;
|
bool optimal;
|
||||||
|
|
||||||
static requirement Texture(const properties &props) {
|
static requirement Texture(const properties &props) {
|
||||||
|
|
|
@ -63,11 +63,11 @@ void framebuffer_size_callback(GLFWwindow *, int width, int height) {
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::Load(Window& window, const renderOptions& opt) {
|
bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
|
||||||
Window::CreateInfo windowInfo;
|
Window::CreateInfo windowInfo;
|
||||||
windowInfo.pfnResize = framebuffer_size_callback;
|
windowInfo.pfnResize = framebuffer_size_callback;
|
||||||
windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR};
|
windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR};
|
||||||
windowInfo.samples = 1;
|
windowInfo.samples = samples;
|
||||||
if (!window.create(windowInfo))
|
if (!window.create(windowInfo))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Renderer final: public render::Renderer {
|
||||||
public:
|
public:
|
||||||
virtual ~Renderer();
|
virtual ~Renderer();
|
||||||
|
|
||||||
static bool Load(Window& window, const renderOptions& options);
|
static bool Load(Window& window, const renderOptions& options, int samples);
|
||||||
|
|
||||||
glm::vec3 FogColor;
|
glm::vec3 FogColor;
|
||||||
GLfloat FogDepth;
|
GLfloat FogDepth;
|
||||||
|
|
|
@ -5,20 +5,20 @@
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
bool Load(Window& window, bool preferVulkan, const renderOptions& options) {
|
bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples) {
|
||||||
if(!preferVulkan) {
|
if(!preferVulkan) {
|
||||||
LOG_T("Trying OpenGL");
|
LOG_T("Trying OpenGL");
|
||||||
if(gl::Renderer::Load(window, options))
|
if(gl::Renderer::Load(window, options, samples))
|
||||||
return true;
|
return true;
|
||||||
window.destroy();
|
window.destroy();
|
||||||
}
|
}
|
||||||
LOG_T("Trying Vulkan");
|
LOG_T("Trying Vulkan");
|
||||||
if(vk::Renderer::Load(window, options))
|
if(vk::Renderer::Load(window, options, samples))
|
||||||
return true;
|
return true;
|
||||||
window.destroy();
|
window.destroy();
|
||||||
if(preferVulkan) {
|
if(preferVulkan) {
|
||||||
LOG_I("Fallback to OpenGL");
|
LOG_I("Fallback to OpenGL");
|
||||||
if(gl::Renderer::Load(window, options))
|
if(gl::Renderer::Load(window, options, samples))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG_E("No available graphics library");
|
LOG_E("No available graphics library");
|
||||||
|
|
|
@ -4,5 +4,5 @@ class Window;
|
||||||
namespace render {
|
namespace render {
|
||||||
struct renderOptions;
|
struct renderOptions;
|
||||||
|
|
||||||
bool Load(Window& window, bool preferVulkan, const renderOptions& options);
|
bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples);
|
||||||
}
|
}
|
|
@ -243,6 +243,12 @@ void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLay
|
||||||
|
|
||||||
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
|
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
|
||||||
|
barrier.srcAccessMask = 0;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
|
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
} else {
|
} else {
|
||||||
FATAL("Unsupported layout transition!");
|
FATAL("Unsupported layout transition!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, co
|
||||||
FATAL("Failed to create texture sampler!");
|
FATAL("Failed to create texture sampler!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
colorFormat = info.getSurfaceFormat().format;
|
||||||
|
colorSamples = info.samples;
|
||||||
|
LOG_D("Samples: " << colorSamples);
|
||||||
depthFormat = info.findDepthFormat();
|
depthFormat = info.findDepthFormat();
|
||||||
}
|
}
|
||||||
CommandCenter::~CommandCenter() {
|
CommandCenter::~CommandCenter() {
|
||||||
|
@ -46,13 +49,25 @@ CommandCenter::~CommandCenter() {
|
||||||
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) {
|
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) {
|
||||||
assert(freed);
|
assert(freed);
|
||||||
|
|
||||||
|
if (colorSamples > 1) {
|
||||||
|
colorbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)colorFormat},
|
||||||
|
Image::Layout::COLOR_ATTACHMENT, Image::Usage::COLOR_ATTACHMENT | Image::Usage::TRANSIENT_ATTACHMENT,
|
||||||
|
Image::Aspect::COLOR, colorSamples));
|
||||||
|
}
|
||||||
|
|
||||||
depthbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)depthFormat},
|
depthbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)depthFormat},
|
||||||
Image::Layout::DEPTH_STENCIL_ATTACHMENT, Image::Usage::DEPTH_STENCIL_ATTACHMENT, Image::Aspect::DEPTH));
|
Image::Layout::DEPTH_STENCIL_ATTACHMENT, Image::Usage::DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
Image::Aspect::DEPTH, colorSamples));
|
||||||
|
|
||||||
framebuffers.resize(views.size());
|
framebuffers.resize(views.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < views.size(); i++) {
|
for (size_t i = 0; i < views.size(); i++) {
|
||||||
std::array<VkImageView, 2> attachments = { views[i], depthbuffer->getView() };
|
std::vector<VkImageView> attachments;
|
||||||
|
if (colorSamples > 1) {
|
||||||
|
attachments = {colorbuffer->getView(), depthbuffer->getView(), views[i]};
|
||||||
|
} else {
|
||||||
|
attachments = {views[i], depthbuffer->getView()};
|
||||||
|
}
|
||||||
|
|
||||||
VkFramebufferCreateInfo framebufferInfo{};
|
VkFramebufferCreateInfo framebufferInfo{};
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
@ -198,6 +213,7 @@ void CommandCenter::free() {
|
||||||
|
|
||||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||||
|
|
||||||
|
colorbuffer.reset();
|
||||||
depthbuffer.reset();
|
depthbuffer.reset();
|
||||||
|
|
||||||
for (size_t i = 0; i < framebuffers.size(); i++) {
|
for (size_t i = 0; i < framebuffers.size(); i++) {
|
||||||
|
@ -216,6 +232,7 @@ void CommandCenter::updateUBO(uint32_t idx) {
|
||||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||||
buffer::vk::UniformBufferObject ubo{};
|
buffer::vk::UniformBufferObject ubo{};
|
||||||
|
time = 0.1;
|
||||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.proj = proj;
|
ubo.proj = proj;
|
||||||
|
|
|
@ -25,6 +25,10 @@ private:
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
|
|
||||||
std::vector<VkFramebuffer> framebuffers;
|
std::vector<VkFramebuffer> framebuffers;
|
||||||
|
|
||||||
|
VkFormat colorFormat;
|
||||||
|
VkSampleCountFlagBits colorSamples;
|
||||||
|
std::unique_ptr<Image> colorbuffer;
|
||||||
VkFormat depthFormat;
|
VkFormat depthFormat;
|
||||||
std::unique_ptr<Image> depthbuffer;
|
std::unique_ptr<Image> depthbuffer;
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,26 @@ struct QueueFamilyIndices {
|
||||||
};
|
};
|
||||||
struct PhysicalDeviceInfo {
|
struct PhysicalDeviceInfo {
|
||||||
PhysicalDeviceInfo() {}
|
PhysicalDeviceInfo() {}
|
||||||
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface):
|
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface, int targetSamples):
|
||||||
window(window), device(device), surface(surface),
|
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))
|
||||||
{
|
{
|
||||||
vkGetPhysicalDeviceProperties(device, &properties);
|
vkGetPhysicalDeviceProperties(device, &properties);
|
||||||
vkGetPhysicalDeviceFeatures(device, &features);
|
vkGetPhysicalDeviceFeatures(device, &features);
|
||||||
|
|
||||||
|
samples = [&] {
|
||||||
|
if (targetSamples < 0)
|
||||||
|
targetSamples = 4;
|
||||||
|
VkSampleCountFlags counts = properties.limits.framebufferColorSampleCounts & properties.limits.framebufferDepthSampleCounts;
|
||||||
|
//MAYBE: properties.limits.framebufferStencilSampleCounts
|
||||||
|
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
|
||||||
|
}) {
|
||||||
|
if (targetSamples >= sample && (counts & sample))
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
return VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSurfaceFormatKHR getSurfaceFormat() const;
|
VkSurfaceFormatKHR getSurfaceFormat() const;
|
||||||
|
@ -44,6 +58,7 @@ struct PhysicalDeviceInfo {
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
VkPhysicalDevice device = VK_NULL_HANDLE;
|
VkPhysicalDevice device = VK_NULL_HANDLE;
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
|
VkSampleCountFlagBits samples;
|
||||||
SwapChainSupportDetails swapDetails;
|
SwapChainSupportDetails swapDetails;
|
||||||
QueueFamilyIndices queueIndices;
|
QueueFamilyIndices queueIndices;
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
|
|
|
@ -13,16 +13,18 @@ constexpr auto BLENDING = true;
|
||||||
using namespace render::vk;
|
using namespace render::vk;
|
||||||
|
|
||||||
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
|
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
|
||||||
|
const auto hasSamples = info.samples > 1;
|
||||||
{ // Render pass
|
{ // Render pass
|
||||||
VkAttachmentDescription colorAttachment{};
|
VkAttachmentDescription colorAttachment{};
|
||||||
colorAttachment.format = info.getSurfaceFormat().format;
|
colorAttachment.format = info.getSurfaceFormat().format;
|
||||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
colorAttachment.samples = info.samples;
|
||||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
colorAttachment.finalLayout = hasSamples ?
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
VkAttachmentReference colorAttachmentRef{};
|
VkAttachmentReference colorAttachmentRef{};
|
||||||
colorAttachmentRef.attachment = 0; //TODO: layouts bind
|
colorAttachmentRef.attachment = 0; //TODO: layouts bind
|
||||||
|
@ -30,7 +32,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
|
|
||||||
VkAttachmentDescription depthAttachment{};
|
VkAttachmentDescription depthAttachment{};
|
||||||
depthAttachment.format = info.findDepthFormat();
|
depthAttachment.format = info.findDepthFormat();
|
||||||
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
depthAttachment.samples = info.samples;
|
||||||
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
@ -42,6 +44,20 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
depthAttachmentRef.attachment = 1;
|
depthAttachmentRef.attachment = 1;
|
||||||
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
VkAttachmentDescription colorAttachmentResolve{};
|
||||||
|
colorAttachmentResolve.format = colorAttachment.format;
|
||||||
|
colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
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;
|
||||||
|
|
||||||
|
VkAttachmentReference colorAttachmentResolveRef{};
|
||||||
|
colorAttachmentResolveRef.attachment = 2;
|
||||||
|
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
//TODO: subpasses (world, entities, colors, sky, ui)
|
//TODO: subpasses (world, entities, colors, sky, ui)
|
||||||
|
|
||||||
VkSubpassDescription subpass{};
|
VkSubpassDescription subpass{};
|
||||||
|
@ -49,6 +65,9 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &colorAttachmentRef;
|
subpass.pColorAttachments = &colorAttachmentRef;
|
||||||
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
||||||
|
if (hasSamples) {
|
||||||
|
subpass.pResolveAttachments = &colorAttachmentResolveRef;
|
||||||
|
}
|
||||||
|
|
||||||
VkSubpassDependency dependency{};
|
VkSubpassDependency dependency{};
|
||||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
@ -60,7 +79,10 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassInfo{};
|
VkRenderPassCreateInfo renderPassInfo{};
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
std::array<VkAttachmentDescription, 2> attachments = {colorAttachment, depthAttachment};
|
std::vector<VkAttachmentDescription> attachments = {colorAttachment, depthAttachment};
|
||||||
|
if (hasSamples) {
|
||||||
|
attachments.push_back(colorAttachmentResolve);
|
||||||
|
}
|
||||||
renderPassInfo.attachmentCount = attachments.size();
|
renderPassInfo.attachmentCount = attachments.size();
|
||||||
renderPassInfo.pAttachments = attachments.data();
|
renderPassInfo.pAttachments = attachments.data();
|
||||||
renderPassInfo.subpassCount = 1;
|
renderPassInfo.subpassCount = 1;
|
||||||
|
@ -190,11 +212,12 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
rasterizer.depthBiasClamp = 0.0f;
|
rasterizer.depthBiasClamp = 0.0f;
|
||||||
rasterizer.depthBiasSlopeFactor = 0.0f;
|
rasterizer.depthBiasSlopeFactor = 0.0f;
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling{}; //TODO: multisampling NOTE: requires gpu feature
|
VkPipelineMultisampleStateCreateInfo multisampling{};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.rasterizationSamples = info.samples;
|
||||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
//MAYBE: add option
|
||||||
multisampling.minSampleShading = 1.0f;
|
multisampling.sampleShadingEnable = hasSamples;
|
||||||
|
multisampling.minSampleShading = .2f;
|
||||||
multisampling.pSampleMask = nullptr;
|
multisampling.pSampleMask = nullptr;
|
||||||
multisampling.alphaToCoverageEnable = VK_FALSE;
|
multisampling.alphaToCoverageEnable = VK_FALSE;
|
||||||
multisampling.alphaToOneEnable = VK_FALSE;
|
multisampling.alphaToOneEnable = VK_FALSE;
|
||||||
|
|
|
@ -155,11 +155,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugValidationCallback(VkDebugUtilsMessageSeveri
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::Load(Window& window, const renderOptions& opt) {
|
bool Renderer::Load(Window& window, const renderOptions& opt, int samples) {
|
||||||
Window::CreateInfo windowInfo;
|
Window::CreateInfo windowInfo;
|
||||||
windowInfo.pfnResize = on_resize_callback;
|
windowInfo.pfnResize = on_resize_callback;
|
||||||
windowInfo.client = {Window::CreateInfo::Client::Type::VK, 0, 0};
|
windowInfo.client = {Window::CreateInfo::Client::Type::VK, 0, 0};
|
||||||
windowInfo.samples = 1;
|
windowInfo.samples = -1;
|
||||||
if (!window.create(windowInfo))
|
if (!window.create(windowInfo))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
||||||
uint bestScore = 0;
|
uint bestScore = 0;
|
||||||
for(const auto& device: devices) {
|
for(const auto& device: devices) {
|
||||||
uint score = 1;
|
uint score = 1;
|
||||||
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface);
|
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, samples);
|
||||||
|
|
||||||
{
|
{
|
||||||
uint32_t availableExtensionsCount;
|
uint32_t availableExtensionsCount;
|
||||||
|
@ -321,6 +321,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
||||||
score += 10000;
|
score += 10000;
|
||||||
|
|
||||||
score += infos.properties.limits.maxImageDimension2D;
|
score += infos.properties.limits.maxImageDimension2D;
|
||||||
|
score += infos.samples * 50;
|
||||||
|
|
||||||
if (infos.features.geometryShader)
|
if (infos.features.geometryShader)
|
||||||
score += 2000;
|
score += 2000;
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Renderer final: public render::Renderer {
|
||||||
public:
|
public:
|
||||||
virtual ~Renderer();
|
virtual ~Renderer();
|
||||||
|
|
||||||
static bool Load(Window& window, const renderOptions& options);
|
static bool Load(Window& window, const renderOptions& options, int samples);
|
||||||
|
|
||||||
void loadUI(Window &) override;
|
void loadUI(Window &) override;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
info.usage = static_cast<VkImageUsageFlags>(req.usage);
|
info.usage = static_cast<VkImageUsageFlags>(req.usage);
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
info.samples = static_cast<VkSampleCountFlagBits>(req.samples);
|
||||||
info.flags = 0;
|
info.flags = 0;
|
||||||
if (data) {
|
if (data) {
|
||||||
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
@ -140,6 +140,10 @@ std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sa
|
||||||
samplerInfo.minLod = 0.0f;
|
samplerInfo.minLod = 0.0f;
|
||||||
samplerInfo.maxLod = props.mipmap ? header.mipmapLevels : 0.0f;
|
samplerInfo.maxLod = props.mipmap ? header.mipmapLevels : 0.0f;
|
||||||
|
|
||||||
|
if (props.mipmap && header.mipmapLevels <= 1) {
|
||||||
|
LOG_D("Sampler requires mipmap but image does not");
|
||||||
|
}
|
||||||
|
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
if (vkCreateSampler(device, &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
if (vkCreateSampler(device, &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create texture sampler!");
|
FATAL("Failed to create texture sampler!");
|
||||||
|
|
|
@ -23,10 +23,10 @@ public:
|
||||||
LOG_E("Config file " << path << " not found. Creating default");
|
LOG_E("Config file " << path << " not found. Creating default");
|
||||||
return toml::table();
|
return toml::table();
|
||||||
}();
|
}();
|
||||||
if (config["server"]["enabled"].value_or(false)) {
|
if (config["server"]["enabled"].value_or(true)) {
|
||||||
_server = server::options(config["server"]);
|
_server = server::options(config["server"]);
|
||||||
}
|
}
|
||||||
if(config["client"]["enabled"].value_or(false)) {
|
if(config["client"]["enabled"].value_or(true)) {
|
||||||
_client = client::options(config["client"]);
|
_client = client::options(config["client"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue