1// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef VK_DEVICE_HPP_
16#define VK_DEVICE_HPP_
17
18#include "VkObject.hpp"
19#include "Device/LRUCache.hpp"
20#include "Reactor/Routine.hpp"
21#include <memory>
22#include <mutex>
23
24namespace marl
25{
26 class Scheduler;
27}
28
29namespace sw
30{
31 class Blitter;
32}
33
34namespace vk
35{
36
37class PhysicalDevice;
38class Queue;
39
40class Device
41{
42public:
43 static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; }
44
45 Device(const VkDeviceCreateInfo* pCreateInfo, void* mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures, const std::shared_ptr<marl::Scheduler>& scheduler);
46 void destroy(const VkAllocationCallbacks* pAllocator);
47
48 static size_t ComputeRequiredAllocationSize(const VkDeviceCreateInfo* pCreateInfo);
49
50 bool hasExtension(const char* extensionName) const;
51 VkQueue getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const;
52 VkResult waitForFences(uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
53 VkResult waitIdle();
54 void getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
55 VkDescriptorSetLayoutSupport* pSupport) const;
56 PhysicalDevice *getPhysicalDevice() const { return physicalDevice; }
57 void updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites,
58 uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
59 const VkPhysicalDeviceFeatures &getEnabledFeatures() const { return enabledFeatures; }
60 sw::Blitter* getBlitter() const { return blitter.get(); }
61
62 class SamplingRoutineCache
63 {
64 public:
65 SamplingRoutineCache() : cache(1024) {}
66 ~SamplingRoutineCache() {}
67
68 struct Key
69 {
70 uint32_t instruction;
71 uint32_t sampler;
72 uint32_t imageView;
73
74 inline bool operator == (const Key& rhs) const;
75
76 struct Hash
77 {
78 inline std::size_t operator()(const Key& key) const noexcept;
79 };
80 };
81
82 std::shared_ptr<rr::Routine> query(const Key& key) const;
83 void add(const Key& key, const std::shared_ptr<rr::Routine>& routine);
84
85 rr::Routine* queryConst(const Key& key) const;
86 void updateConstCache();
87
88 private:
89 sw::LRUConstCache<Key, std::shared_ptr<rr::Routine>, Key::Hash> cache;
90 };
91
92 SamplingRoutineCache* getSamplingRoutineCache() const;
93 std::mutex& getSamplingRoutineCacheMutex();
94 rr::Routine* findInConstCache(const SamplingRoutineCache::Key& key) const;
95 void updateSamplingRoutineConstCache();
96
97private:
98 PhysicalDevice *const physicalDevice = nullptr;
99 Queue *const queues = nullptr;
100 uint32_t queueCount = 0;
101 std::unique_ptr<sw::Blitter> blitter;
102 std::unique_ptr<SamplingRoutineCache> samplingRoutineCache;
103 std::mutex samplingRoutineCacheMutex;
104 uint32_t enabledExtensionCount = 0;
105 typedef char ExtensionName[VK_MAX_EXTENSION_NAME_SIZE];
106 ExtensionName* extensions = nullptr;
107 const VkPhysicalDeviceFeatures enabledFeatures = {};
108 std::shared_ptr<marl::Scheduler> scheduler;
109};
110
111using DispatchableDevice = DispatchableObject<Device, VkDevice>;
112
113static inline Device* Cast(VkDevice object)
114{
115 return DispatchableDevice::Cast(object);
116}
117
118inline bool vk::Device::SamplingRoutineCache::Key::operator == (const Key& rhs) const
119{
120 return instruction == rhs.instruction && sampler == rhs.sampler && imageView == rhs.imageView;
121}
122
123inline std::size_t vk::Device::SamplingRoutineCache::Key::Hash::operator() (const Key& key) const noexcept
124{
125 // Combine three 32-bit integers into a 64-bit hash.
126 // 2642239 is the largest prime which when cubed is smaller than 2^64.
127 uint64_t hash = key.instruction;
128 hash = (hash * 2642239) ^ key.sampler;
129 hash = (hash * 2642239) ^ key.imageView;
130 return static_cast<std::size_t>(hash); // Truncates to 32-bits on 32-bit platforms.
131}
132
133} // namespace vk
134
135#endif // VK_DEVICE_HPP_
136