Skip to content

Commit

Permalink
Merge pull request #3 from Hjaltesorgenfrei/compute-shader
Browse files Browse the repository at this point in the history
Compute shader
  • Loading branch information
Hjaltesorgenfrei authored Mar 1, 2023
2 parents 1c3e9ee + 29a8564 commit d7edde6
Show file tree
Hide file tree
Showing 21 changed files with 595 additions and 158 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ cmake-build-debug/*
cmake-build-*/*
Makefile

## Clion
.cmake/
.ninja_deps
.ninja_log
build.ninja

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)

project(vulkanologi)

Expand Down Expand Up @@ -97,9 +97,12 @@ target_precompile_headers(vulkanologi PRIVATE src/BehDevice.h src/WindowWrapper.
target_link_libraries(vulkanologi glfw glm tinyobjloader VulkanMemoryAllocator Vulkan::Vulkan)
add_shader(vulkanologi shader.frag)
add_shader(vulkanologi shader.vert)
add_shader(vulkanologi particle.frag)
add_shader(vulkanologi particle.vert)
add_shader(vulkanologi shader_unlit.frag)
add_shader(vulkanologi shader_unlit.vert)
add_shader(vulkanologi point_light.frag)
add_shader(vulkanologi point_light.vert)
add_shader(vulkanologi particles.comp)

add_dependencies(vulkanologi copy-runtime-files)
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A Vulkan Renderer written in C++ 20. Very much WIP.

![Readme Image](docs/readme.png)

## Building

To build on Windows install the Vulkan SDK from <https://vulkan.lunarg.com/sdk/home#windows> and set the enviroment variable `VULKAN_HOME` to the install location.
Expand Down Expand Up @@ -92,6 +94,8 @@ Some ideas were also taken from [Zeux's blog](https://zeux.io/2020/02/27/writing
- [x] use imageless framebuffer
- [x] If the items in 4 and 5 are implemented, the resize function will not need to call vkDeviceWaitIdle()
- [ ] Implement Compute shaders <https://github.com/Overv/VulkanTutorial/pull/320>
- [ ] Delete `Renderer::uploadBuffer` it should be handled by `AssetManager`
- [ ] Create multiple vk::Framebuffer swapChainFramebuffers.

### Descriptor Layout Idea

Expand Down
Binary file added docs/readme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void App::keyCallback(GLFWwindow* window, int key, int scancode, int action, int
}
}

int App::drawFrame() {
int App::drawFrame(double delta) {
// std::lock_guard<std::mutex> lockGuard(rendererMutex);
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
Expand All @@ -113,19 +113,25 @@ int App::drawFrame() {
FrameInfo frameInfo{};
frameInfo.objects = objects;
frameInfo.camera = camera;
frameInfo.deltaTime = delta;

auto result = renderer->drawFrame(frameInfo);
ImGui::EndFrame();
return result;
}

void App::drawLoop() {
auto timeStart = std::chrono::high_resolution_clock::now();
while (!window->windowShouldClose()) {
auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> delta = now - timeStart;
timeStart = now;
window->setTitle(std::to_string(delta.count()).c_str());
if (updateWindowSize) {
renderer->recreateSwapchain();
updateWindowSize = false;
}
auto result = drawFrame();
auto result = drawFrame(delta.count());
if (result == 1) {
renderer->recreateSwapchain();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ class App {

void drawLoop();

int drawFrame();
int drawFrame(double delta);

};
4 changes: 2 additions & 2 deletions src/AssetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void AssetManager::createTextureImage(const char *filename, const std::shared_pt
texture->mipLevels);
copyBufferToImage(stagingBuffer._buffer, texture->textureImage._image, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));

cleanUpStagingBuffer(stagingBuffer);
cleanUpBuffer(stagingBuffer);

generateMipmaps(texture->textureImage._image, vk::Format::eR8G8B8A8Srgb, texWidth, texHeight, texture->mipLevels);
deletionQueue.push_function([&, texture]() {
Expand Down Expand Up @@ -91,7 +91,7 @@ void AssetManager::createTextureSampler(const std::shared_ptr<UploadedTexture>&
}


void AssetManager::cleanUpStagingBuffer(AllocatedBuffer buffer) {
void AssetManager::cleanUpBuffer(AllocatedBuffer buffer) {
vmaDestroyBuffer(device->allocator(), buffer._buffer, buffer._allocation);
}

Expand Down
61 changes: 52 additions & 9 deletions src/AssetManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class AssetManager {

[[nodiscard]] AllocatedImage createImage(int width, int height, uint32_t mipLevels, vk::SampleCountFlagBits numSamples, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags flags);

template <typename T>
[[nodiscard]] std::vector<std::shared_ptr<AllocatedBuffer>> createBuffers(std::span<T> data, vk::BufferUsageFlags bufferUsage, size_t count = 1);

private:
std::shared_ptr<BehDevice> device;

Expand All @@ -45,7 +48,7 @@ class AssetManager {
template <typename T>
[[nodiscard]] AllocatedBuffer stageData(std::span<T>& dataToStage);

void cleanUpStagingBuffer(AllocatedBuffer buffer);
void cleanUpBuffer(AllocatedBuffer buffer);

void transitionImageLayout(vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, uint32_t mipLevels);

Expand All @@ -58,22 +61,22 @@ class AssetManager {

template <typename T>
inline AllocatedBuffer AssetManager::stageData(std::span<T>& dataToStage) {
VkBufferCreateInfo stagingCreate{
VkBufferCreateInfo stagingCreate {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = dataToStage.size() * sizeof(T),
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
};

VmaAllocationCreateInfo stagingAlloc{
VmaAllocationCreateInfo stagingAlloc {
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
.usage = VMA_MEMORY_USAGE_AUTO};
.usage = VMA_MEMORY_USAGE_AUTO
};

VkBuffer buffer;
AllocatedBuffer stagingBuffer{};

if (vmaCreateBuffer(device->allocator(), &stagingCreate, &stagingAlloc, &buffer, &stagingBuffer._allocation, nullptr) != VK_SUCCESS) {
throw std::runtime_error("Failed to uploadBuffer mesh vertices!");
if (vmaCreateBuffer(device->allocator(), &stagingCreate, &stagingAlloc, reinterpret_cast<VkBuffer *>(&stagingBuffer._buffer), &stagingBuffer._allocation, nullptr) != VK_SUCCESS) {
throw std::runtime_error("Failed to create staging buffer!");
}
stagingBuffer._buffer = buffer;

void* data;
vmaMapMemory(device->allocator(), stagingBuffer._allocation, &data);
Expand All @@ -83,3 +86,43 @@ inline AllocatedBuffer AssetManager::stageData(std::span<T>& dataToStage) {
vmaUnmapMemory(device->allocator(), stagingBuffer._allocation);
return stagingBuffer;
}

template <typename T>
inline std::vector<std::shared_ptr<AllocatedBuffer>> AssetManager::createBuffers(std::span<T> data, vk::BufferUsageFlags bufferUsage, size_t count) {
auto stagedBuffer = stageData(data);
auto size = data.size() * sizeof(T);

VkBufferCreateInfo createInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.usage = static_cast<VkBufferUsageFlags>(bufferUsage)
};

VmaAllocationCreateInfo allocInfo {
.usage = VMA_MEMORY_USAGE_AUTO
};

std::vector<std::shared_ptr<AllocatedBuffer>> buffers;

for (int i = 0; i < count; i++) {
std::shared_ptr<AllocatedBuffer> buffer = std::make_shared<AllocatedBuffer>();
if (vmaCreateBuffer(device->allocator(), &createInfo, &allocInfo, reinterpret_cast<VkBuffer*>(&buffer->_buffer), &buffer->_allocation, nullptr) != VK_SUCCESS) {
throw std::runtime_error("Failed to create buffer!");
}
buffers.push_back(buffer);
deletionQueue.push_function([buffer, this](){
cleanUpBuffer(*buffer);
});
}

device->immediateSubmit([&](auto cmd) {
vk::BufferCopy copyRegion{
.size = size
};
for (int i = 0; i < count; i++) {
cmd.copyBuffer(stagedBuffer._buffer, buffers[i]->_buffer, 1, &copyRegion);
}
});
cleanUpBuffer(stagedBuffer);
return buffers;
}
2 changes: 1 addition & 1 deletion src/BehDescriptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ bool DescriptorSetLayoutBuilder::validate() {

for (size_t i = 0; i < bindings.size(); i++) {
const auto &binding = bindings[i];
if (i + 1 < bindings.size() && bindings[i].binding <= binding.binding) {
if (i + 1 < bindings.size() && bindings[i + 1].binding <= binding.binding) {
std::cerr
<< "Please add your bindings in order. This check might be removed later if I sort the order later.\n";
result = false;
Expand Down
11 changes: 6 additions & 5 deletions src/BehDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void BehDevice::createLogicalDevice() {
QueueFamilyIndices indices = findQueueFamilies(_physicalDevice, _surface);

std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value(),
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsAndComputeFamily.value(), indices.presentFamily.value(),
indices.transferFamily.value()};

float queuePriority = 1.0f;
Expand Down Expand Up @@ -195,7 +195,8 @@ void BehDevice::createLogicalDevice() {
throw std::runtime_error(std::string("Failed to create logical device!") + err.what());
}

_device.getQueue(indices.graphicsFamily.value(), 0, &_graphicsQueue);
_device.getQueue(indices.graphicsAndComputeFamily.value(), 0, &_graphicsQueue);
_device.getQueue(indices.graphicsAndComputeFamily.value(), 0, &_computeQueue);
_device.getQueue(indices.presentFamily.value(), 0, &_presentQueue);
_device.getQueue(indices.transferFamily.value(), 0, &_transferQueue);
}
Expand All @@ -217,7 +218,7 @@ void BehDevice::createUploadContext() {
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(_physicalDevice, _surface);

const vk::CommandPoolCreateInfo uploadPoolInfo{
.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value()
.queueFamilyIndex = queueFamilyIndices.graphicsAndComputeFamily.value()
};

try {
Expand Down Expand Up @@ -456,8 +457,8 @@ QueueFamilyIndices BehDevice::findQueueFamilies(vk::PhysicalDevice device, vk::S
for (const auto &queueFamily: queueFamilies) {
// documentation of VkQueueFamilyProperties states that "Each queue family must support at least one queue".

if (queueFamily.queueFlags & vk::QueueFlagBits::eGraphics) {
indices.graphicsFamily = i;
if (queueFamily.queueFlags & vk::QueueFlagBits::eGraphics && queueFamily.queueFlags & vk::QueueFlagBits::eCompute) {
indices.graphicsAndComputeFamily = i;
}

if (device.getSurfaceSupportKHR(i, surface)) {
Expand Down
6 changes: 4 additions & 2 deletions src/BehDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ const bool enableValidationLayers = true;
#endif

struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> graphicsAndComputeFamily;
std::optional<uint32_t> presentFamily;
std::optional<uint32_t> transferFamily;

[[nodiscard]] bool isComplete() const {
return graphicsFamily.has_value() && presentFamily.has_value() && transferFamily.has_value();
return graphicsAndComputeFamily.has_value() && presentFamily.has_value() && transferFamily.has_value();
}
};

Expand Down Expand Up @@ -55,6 +55,7 @@ class BehDevice {
vk::Instance instance() { return _instance; }
vk::Queue graphicsQueue() {return _graphicsQueue; }
vk::Queue presentQueue() {return _presentQueue; }
vk::Queue computeQueue() {return _computeQueue; }
vk::SampleCountFlagBits msaaSamples() { return _msaaSamples; }
VmaAllocator allocator() { return _allocator; }

Expand Down Expand Up @@ -103,6 +104,7 @@ class BehDevice {

vk::Queue _presentQueue;
vk::Queue _graphicsQueue;
vk::Queue _computeQueue;

vk::Queue _transferQueue;
UploadContext _uploadContext;
Expand Down
6 changes: 4 additions & 2 deletions src/BehFrameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ struct GlobalUbo {
glm::mat4 proj;
glm::mat4 projView;
glm::vec4 ambientLightColor{1.f, 1.f, 1.f, .04f}; // w is intensity
glm::vec4 lightPosition{2.f, 1.f, 0.0f, 0.0f}; // w is ignored
glm::vec4 lightColor{1.f}; // w is light intensity
glm::vec4 lightPosition{2.f, 13.5f, 0.0f, 0.0f}; // w is ignored
glm::vec4 lightColor{1.f, 1.f, 1.f, 3.f}; // w is light intensity
float deltaTime;
};

struct FrameInfo {
BehCamera camera;
std::vector<std::shared_ptr<RenderObject>> objects{};
float deltaTime = 0.16f;
};
Loading

0 comments on commit d7edde6

Please sign in to comment.