You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.7 KiB
198 lines
6.7 KiB
4 months ago
|
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
#ifndef DRAW_TESTER_HPP_
|
||
|
#define DRAW_TESTER_HPP_
|
||
|
|
||
|
#include "Framebuffer.hpp"
|
||
|
#include "Image.hpp"
|
||
|
#include "Swapchain.hpp"
|
||
|
#include "Util.hpp"
|
||
|
#include "VulkanTester.hpp"
|
||
|
#include "Window.hpp"
|
||
|
|
||
|
enum class Multisample
|
||
|
{
|
||
|
False,
|
||
|
True
|
||
|
};
|
||
|
|
||
|
class DrawTester : public VulkanTester
|
||
|
{
|
||
|
public:
|
||
|
using ThisType = DrawTester;
|
||
|
|
||
|
DrawTester(Multisample multisample = Multisample::False);
|
||
|
~DrawTester();
|
||
|
|
||
|
void initialize();
|
||
|
void renderFrame();
|
||
|
void show();
|
||
|
|
||
|
/////////////////////////
|
||
|
// Hooks
|
||
|
/////////////////////////
|
||
|
|
||
|
// Called from prepareVertices.
|
||
|
// Callback may call tester.addVertexBuffer() from this function.
|
||
|
void onCreateVertexBuffers(std::function<void(ThisType &tester)> callback);
|
||
|
|
||
|
// Called from createGraphicsPipeline.
|
||
|
// Callback must return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout
|
||
|
// will be created and stored in this->descriptorSetLayout.
|
||
|
void onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback);
|
||
|
|
||
|
// Called from createGraphicsPipeline.
|
||
|
// Callback should call tester.createShaderModule() and return the result.
|
||
|
void onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
|
||
|
|
||
|
// Called from createGraphicsPipeline.
|
||
|
// Callback should call tester.createShaderModule() and return the result.
|
||
|
void onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
|
||
|
|
||
|
// Called from createCommandBuffers.
|
||
|
// Callback may create resources (tester.addImage, tester.addSampler, etc.), and make sure to
|
||
|
// call tester.device().updateDescriptorSets.
|
||
|
void onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback);
|
||
|
|
||
|
/////////////////////////
|
||
|
// Resource Management
|
||
|
/////////////////////////
|
||
|
|
||
|
// Call from doCreateFragmentShader()
|
||
|
vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage);
|
||
|
|
||
|
// Call from doCreateVertexBuffers()
|
||
|
template<typename VertexType>
|
||
|
void addVertexBuffer(VertexType *vertexBufferData, size_t vertexBufferDataSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
|
||
|
{
|
||
|
addVertexBuffer(vertexBufferData, vertexBufferDataSize, sizeof(VertexType), std::move(inputAttributes));
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
struct Resource
|
||
|
{
|
||
|
size_t id;
|
||
|
T &obj;
|
||
|
};
|
||
|
|
||
|
template<typename... Args>
|
||
|
Resource<Image> addImage(Args &&... args)
|
||
|
{
|
||
|
images.emplace_back(std::make_unique<Image>(std::forward<Args>(args)...));
|
||
|
return { images.size() - 1, *images.back() };
|
||
|
}
|
||
|
|
||
|
Image &getImageById(size_t id)
|
||
|
{
|
||
|
return *images[id].get();
|
||
|
}
|
||
|
|
||
|
Resource<vk::Sampler> addSampler(const vk::SamplerCreateInfo &samplerCreateInfo)
|
||
|
{
|
||
|
auto sampler = device.createSampler(samplerCreateInfo);
|
||
|
samplers.push_back(sampler);
|
||
|
return { samplers.size() - 1, samplers.back() };
|
||
|
}
|
||
|
|
||
|
vk::Sampler &getSamplerById(size_t id)
|
||
|
{
|
||
|
return samplers[id];
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void createSynchronizationPrimitives();
|
||
|
void createCommandBuffers(vk::RenderPass renderPass);
|
||
|
void prepareVertices();
|
||
|
void createFramebuffers(vk::RenderPass renderPass);
|
||
|
vk::RenderPass createRenderPass(vk::Format colorFormat);
|
||
|
vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
|
||
|
void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
|
||
|
|
||
|
struct Hook
|
||
|
{
|
||
|
std::function<void(ThisType &tester)> createVertexBuffers = [](auto &) {};
|
||
|
std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> createDescriptorSetLayout = [](auto &) { return std::vector<vk::DescriptorSetLayoutBinding>{}; };
|
||
|
std::function<vk::ShaderModule(ThisType &tester)> createVertexShader = [](auto &) { return vk::ShaderModule{}; };
|
||
|
std::function<vk::ShaderModule(ThisType &tester)> createFragmentShader = [](auto &) { return vk::ShaderModule{}; };
|
||
|
std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> updateDescriptorSet = [](auto &, auto &, auto &) {};
|
||
|
} hooks;
|
||
|
|
||
|
const vk::Extent2D windowSize = { 1280, 720 };
|
||
|
const bool multisample;
|
||
|
|
||
|
std::unique_ptr<Window> window;
|
||
|
std::unique_ptr<Swapchain> swapchain;
|
||
|
|
||
|
vk::RenderPass renderPass; // Owning handle
|
||
|
std::vector<std::unique_ptr<Framebuffer>> framebuffers;
|
||
|
uint32_t currentFrameBuffer = 0;
|
||
|
|
||
|
struct VertexBuffer
|
||
|
{
|
||
|
vk::Buffer buffer; // Owning handle
|
||
|
vk::DeviceMemory memory; // Owning handle
|
||
|
|
||
|
vk::VertexInputBindingDescription inputBinding;
|
||
|
std::vector<vk::VertexInputAttributeDescription> inputAttributes;
|
||
|
vk::PipelineVertexInputStateCreateInfo inputState;
|
||
|
|
||
|
uint32_t numVertices = 0;
|
||
|
} vertices;
|
||
|
|
||
|
vk::DescriptorSetLayout descriptorSetLayout; // Owning handle
|
||
|
vk::PipelineLayout pipelineLayout; // Owning handle
|
||
|
vk::Pipeline pipeline; // Owning handle
|
||
|
|
||
|
vk::Semaphore presentCompleteSemaphore; // Owning handle
|
||
|
vk::Semaphore renderCompleteSemaphore; // Owning handle
|
||
|
std::vector<vk::Fence> waitFences; // Owning handles
|
||
|
|
||
|
vk::CommandPool commandPool; // Owning handle
|
||
|
vk::DescriptorPool descriptorPool; // Owning handle
|
||
|
|
||
|
// Resources
|
||
|
std::vector<std::unique_ptr<Image>> images;
|
||
|
std::vector<vk::Sampler> samplers; // Owning handles
|
||
|
|
||
|
std::vector<vk::CommandBuffer> commandBuffers; // Owning handles
|
||
|
};
|
||
|
|
||
|
inline void DrawTester::onCreateVertexBuffers(std::function<void(ThisType &tester)> callback)
|
||
|
{
|
||
|
hooks.createVertexBuffers = std::move(callback);
|
||
|
}
|
||
|
|
||
|
inline void DrawTester::onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback)
|
||
|
{
|
||
|
hooks.createDescriptorSetLayout = std::move(callback);
|
||
|
}
|
||
|
|
||
|
inline void DrawTester::onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
|
||
|
{
|
||
|
hooks.createVertexShader = std::move(callback);
|
||
|
}
|
||
|
|
||
|
inline void DrawTester::onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
|
||
|
{
|
||
|
hooks.createFragmentShader = std::move(callback);
|
||
|
}
|
||
|
|
||
|
inline void DrawTester::onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback)
|
||
|
{
|
||
|
hooks.updateDescriptorSet = std::move(callback);
|
||
|
}
|
||
|
|
||
|
#endif // DRAW_TESTER_HPP_
|