Blender V4.5
vk_push_constants.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
19
20#pragma once
21
22#include "BLI_utility_mixins.hh"
23#include "BLI_vector.hh"
24
26
27#include "vk_common.hh"
28#include "vk_descriptor_set.hh"
29
30namespace blender::gpu {
32class VKUniformBuffer;
33class VKContext;
34class VKDevice;
35
48class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
49 friend class VKContext;
50
51 public:
65
69 struct Layout {
72
73 struct PushConstant {
74 /* Used as lookup based on ShaderInput. */
76
78 uint32_t offset;
82 };
83
84 private:
85 Vector<PushConstant> push_constants;
86 uint32_t size_in_bytes_ = 0;
87 StorageType storage_type_ = StorageType::NONE;
91 VKDescriptorSet::Location descriptor_set_location_;
92
93 public:
105 const VKDevice &device);
106
117 void init(const shader::ShaderCreateInfo &info,
119 StorageType storage_type,
121
126 {
127 return storage_type_;
128 }
129
136 {
137 return descriptor_set_location_;
138 }
139
143 uint32_t size_in_bytes() const
144 {
145 return size_in_bytes_;
146 }
147
152 const PushConstant *find(int32_t location) const;
153
154 void debug_print() const;
155 };
156
157 private:
158 const Layout *layout_ = nullptr;
159 void *data_ = nullptr;
160 bool is_dirty_ = false;
161
162 public:
164 VKPushConstants(const Layout *layout);
166 virtual ~VKPushConstants();
167
169
170 size_t offset() const
171 {
172 return 0;
173 }
174
175 const Layout &layout_get() const
176 {
177 return *layout_;
178 }
179
183 std::unique_ptr<VKUniformBuffer> create_resource(VKContext &context) override;
184
192 const void *data() const
193 {
194 return data_;
195 }
196
205 template<typename T>
207 int32_t comp_len,
208 int32_t array_size,
209 const T *input_data)
210 {
211 const Layout::PushConstant *push_constant_layout = layout_->find(location);
212 if (push_constant_layout == nullptr) {
213 /* Legacy code can still try to update push constants when they don't exist. For example
214 * `immDrawPixelsTexSetup` will bind an image slot manually. This works in OpenGL, but in
215 * vulkan images aren't stored as push constants. */
216 return;
217 }
218
219 uint8_t *bytes = static_cast<uint8_t *>(data_);
220 T *dst = static_cast<T *>(static_cast<void *>(&bytes[push_constant_layout->offset]));
221 const int inner_row_padding = push_constant_layout->inner_row_padding;
222 const bool is_tightly_std140_packed = (comp_len % 4) == 0;
223 /* Vec3[] are not tightly packed in std430. */
224 const bool is_tightly_std430_packed = comp_len != 3 || array_size == 0;
225 if (inner_row_padding == 0 &&
226 ((layout_->storage_type_get() == StorageType::PUSH_CONSTANTS &&
227 is_tightly_std430_packed) ||
228 array_size == 0 || push_constant_layout->array_size == 0 || is_tightly_std140_packed))
229 {
230 const size_t copy_size_in_bytes = comp_len * max_ii(array_size, 1) * sizeof(T);
231 BLI_assert_msg(push_constant_layout->offset + copy_size_in_bytes <= layout_->size_in_bytes(),
232 "Tried to write outside the push constant allocated memory.");
233 memcpy(dst, input_data, copy_size_in_bytes);
234 is_dirty_ = true;
235 return;
236 }
237
238 /* Store elements in uniform buffer as array. In Std140 arrays have an element stride of 16
239 * bytes. */
240 BLI_assert(sizeof(T) == 4);
241 const T *src = input_data;
242 if (inner_row_padding == 0) {
243 for (const int i : IndexRange(array_size)) {
244 UNUSED_VARS(i);
245 memcpy(dst, src, comp_len * sizeof(T));
246 src += comp_len;
247 dst += 4;
248 }
249 }
250 else {
251 BLI_assert_msg(array_size == 1, "No support for MAT3 arrays, but can be added when needed");
252 for (const int component_index : IndexRange(comp_len)) {
253 *dst = *src;
254 dst += 1;
255 src += 1;
256 if ((component_index % inner_row_padding) == (inner_row_padding - 1)) {
257 dst += 1;
258 }
259 }
260 }
261
262 is_dirty_ = true;
263 }
264
272
278 std::unique_ptr<VKUniformBuffer> &uniform_buffer_get();
279};
280
281} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
MINLINE int max_ii(int a, int b)
unsigned int uint
#define UNUSED_VARS(...)
void init()
VKPushConstants & operator=(VKPushConstants &&other)
std::unique_ptr< VKUniformBuffer > create_resource(VKContext &context) override
const Layout & layout_get() const
std::unique_ptr< VKUniformBuffer > & uniform_buffer_get()
void push_constant_set(int32_t location, int32_t comp_len, int32_t array_size, const T *input_data)
#define T
static constexpr StorageType STORAGE_TYPE_DEFAULT
static constexpr StorageType STORAGE_TYPE_FALLBACK
static StorageType determine_storage_type(const shader::ShaderCreateInfo &info, const VKDevice &device)
VKDescriptorSet::Location descriptor_set_location_get() const
const PushConstant * find(int32_t location) const
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
i
Definition text_draw.cc:230