Blender V5.0
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
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
162 std::unique_ptr<VKUniformBuffer> uniform_buffer_;
163
164 public:
166 VKPushConstants(const Layout *layout);
168 virtual ~VKPushConstants();
169
171
172 size_t offset() const
173 {
174 return 0;
175 }
176
177 const Layout &layout_get() const
178 {
179 return *layout_;
180 }
181
189 const void *data() const
190 {
191 return data_;
192 }
193
202 template<typename T>
204 int32_t comp_len,
205 int32_t array_size,
206 const T *input_data)
207 {
208 const Layout::PushConstant *push_constant_layout = layout_->find(location);
209 if (push_constant_layout == nullptr) {
210 /* Legacy code can still try to update push constants when they don't exist. For example
211 * `immDrawPixelsTexSetup` will bind an image slot manually. This works in OpenGL, but in
212 * vulkan images aren't stored as push constants. */
213 return;
214 }
215
216 uint8_t *bytes = static_cast<uint8_t *>(data_);
217 T *dst = static_cast<T *>(static_cast<void *>(&bytes[push_constant_layout->offset]));
218 const int inner_row_padding = push_constant_layout->inner_row_padding;
219 const bool is_tightly_std140_packed = (comp_len % 4) == 0;
220 /* Vec3[] are not tightly packed in std430. */
221 const bool is_tightly_std430_packed = comp_len != 3 || array_size == 0;
222 if (inner_row_padding == 0 &&
223 ((layout_->storage_type_get() == StorageType::PUSH_CONSTANTS &&
224 is_tightly_std430_packed) ||
225 array_size == 0 || push_constant_layout->array_size == 0 || is_tightly_std140_packed))
226 {
227 const size_t copy_size_in_bytes = comp_len * max_ii(array_size, 1) * sizeof(T);
228 BLI_assert_msg(push_constant_layout->offset + copy_size_in_bytes <= layout_->size_in_bytes(),
229 "Tried to write outside the push constant allocated memory.");
230 memcpy(dst, input_data, copy_size_in_bytes);
231 return;
232 }
233
234 /* Store elements in uniform buffer as array. In Std140 arrays have an element stride of 16
235 * bytes. */
236 BLI_assert(sizeof(T) == 4);
237 const T *src = input_data;
238 if (inner_row_padding == 0) {
239 for (const int i : IndexRange(array_size)) {
240 UNUSED_VARS(i);
241 memcpy(dst, src, comp_len * sizeof(T));
242 src += comp_len;
243 dst += 4;
244 }
245 }
246 else {
247 BLI_assert_msg(array_size == 1, "No support for MAT3 arrays, but can be added when needed");
248 for (const int component_index : IndexRange(comp_len)) {
249 *dst = *src;
250 dst += 1;
251 src += 1;
252 if ((component_index % inner_row_padding) == (inner_row_padding - 1)) {
253 dst += 1;
254 }
255 }
256 }
257 }
258
266
272 std::unique_ptr<VKUniformBuffer> &uniform_buffer_get();
273};
274
275} // 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)
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