blob: a9128a92ac7233176369364c6fd5c42d387d9609 [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "WebGPU.h"
#include <memory>
#include <cstdint>
#include <string>
#include <vector>
#include <list>
#include <unordered_map>
#include <vulkan/vulkan.hpp>
#include "QueueImpl.h"
#include "BufferImpl.h"
#include "TextureImpl.h"
#include "SamplerImpl.h"
#include "RenderStateImpl.h"
#include "ComputeStateImpl.h"
#include <cassert>
namespace WebGPU {
class DeviceImpl : public Device {
public:
DeviceImpl() = default;
virtual ~DeviceImpl();
DeviceImpl(const DeviceImpl&) = delete;
DeviceImpl(DeviceImpl&&) = default;
DeviceImpl& operator=(const DeviceImpl&) = delete;
DeviceImpl& operator=(DeviceImpl&&) = default;
DeviceImpl(HINSTANCE hInstance, HWND hWnd);
private:
class UniqueDebugReportCallbackEXT {
public:
UniqueDebugReportCallbackEXT() = default;
UniqueDebugReportCallbackEXT(const UniqueDebugReportCallbackEXT&) = delete;
UniqueDebugReportCallbackEXT(UniqueDebugReportCallbackEXT&& other) : debugReportCallback(std::move(other.debugReportCallback)), instance(std::move(other.instance)) {
other.debugReportCallback = vk::DebugReportCallbackEXT();
}
UniqueDebugReportCallbackEXT& operator=(const UniqueDebugReportCallbackEXT&) = delete;
UniqueDebugReportCallbackEXT& operator=(UniqueDebugReportCallbackEXT&& other) {
destroy();
debugReportCallback = std::move(other.debugReportCallback);
instance = std::move(other.instance);
other.debugReportCallback = vk::DebugReportCallbackEXT();
return *this;
}
UniqueDebugReportCallbackEXT(const vk::Instance& instance, const vk::DebugReportCallbackCreateInfoEXT& info) : instance(instance) {
PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(instance.getProcAddr("vkCreateDebugReportCallbackEXT"));
assert(createDebugReportCallback != nullptr);
const VkDebugReportCallbackCreateInfoEXT infoValue = info;
VkDebugReportCallbackEXT debugReportCallback;
auto result = createDebugReportCallback(instance, &infoValue, nullptr, &debugReportCallback);
assert(result == VK_SUCCESS);
this->debugReportCallback = debugReportCallback;
}
~UniqueDebugReportCallbackEXT() {
destroy();
}
void destroy() {
if (debugReportCallback != vk::DebugReportCallbackEXT()) {
PFN_vkDestroyDebugReportCallbackEXT destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(instance.getProcAddr("vkDestroyDebugReportCallbackEXT"));
assert(destroyDebugReportCallback != nullptr);
destroyDebugReportCallback(instance, debugReportCallback, nullptr);
}
}
vk::DebugReportCallbackEXT debugReportCallback;
vk::Instance instance;
};
Queue& getCommandQueue() override;
RenderState& getRenderState(const std::vector<uint8_t>& vertexShader, const std::string& vertexShaderName, const std::vector<uint8_t>& fragmentShader, const std::string& fragmentShaderName, const std::vector<unsigned int>& vertexAttributeBufferStrides, const std::vector<RenderState::VertexAttribute>& vertexAttributes, const std::vector<std::vector<ResourceType>>& resources, const std::vector<PixelFormat>* colorPixelFormats) override;
ComputeState& getComputeState(const std::vector<uint8_t>& shader, const std::string& shaderName, const std::vector<std::vector<ResourceType>>& resources) override;
BufferHolder getBuffer(unsigned int length) override;
void returnBuffer(Buffer&) override;
TextureHolder getTexture(unsigned int width, unsigned int height, PixelFormat format) override;
void returnTexture(Texture&) override;
SamplerHolder getSampler(AddressMode addressMode, Filter filter) override;
void returnSampler(Sampler&) override;
vk::UniqueShaderModule prepareShader(const std::vector<uint8_t>& shader);
std::pair<vk::UniquePipelineLayout, std::vector<vk::UniqueDescriptorSetLayout>> createPipelineLayout(const std::vector<std::vector<ResourceType>>& resources);
vk::UniqueRenderPass createCompatibleRenderPass(const std::vector<PixelFormat>* colorPixelFormats);
vk::UniqueInstance instance;
UniqueDebugReportCallbackEXT debugReportCallback;
vk::PhysicalDevice gpu;
vk::UniqueSurfaceKHR surface;
vk::UniqueDevice device;
vk::PhysicalDeviceMemoryProperties memoryProperties;
vk::UniqueSwapchainKHR swapchain;
std::vector<vk::Image> swapchainImages;
std::vector<vk::UniqueImageView> swapchainImageViews;
vk::UniquePipelineCache pipelineCache;
std::unique_ptr<QueueImpl> queue;
vk::UniqueCommandPool commandPool;
std::list<RenderStateImpl> renderStates;
std::list<ComputeStateImpl> computeStates;
template<typename T>
struct ResourcePool {
std::list<T> inUse;
std::list<T> freeList;
};
std::unordered_map<unsigned int, ResourcePool<BufferImpl>> bufferCache;
struct TextureParameters {
bool operator==(const TextureParameters& other) const {
return width == other.width && height == other.height && format == other.format;
}
unsigned int width;
unsigned int height;
PixelFormat format;
};
struct TextureParametersHash {
std::size_t operator()(const TextureParameters& textureParameters) const {
std::hash<unsigned int> uintHash;
return uintHash(textureParameters.width) | uintHash(textureParameters.height) | uintHash(static_cast<unsigned int>(textureParameters.format));
}
};
std::unordered_map<TextureParameters, ResourcePool<TextureImpl>, TextureParametersHash> textureCache;
std::unordered_map<uint32_t, ResourcePool<SamplerImpl>> samplerCache;
};
}