MXVK Vulkan Framework 0.33.1
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk::VKAbstractModel Class Reference

Convenience wrapper that owns mesh, textures, descriptors, and pipeline state. More...

#include <mxvk/include/mxvk/mxvk_abstract_model.hpp>

Public Member Functions

void cleanup (VK_Window *window)
 Destroy all owned Vulkan resources.
void enableExtendedFragmentUniforms ()
 Use binding 1 for fragment uniforms and binding 2 for model transforms.
bool isLoaded () const
 True once the model has been uploaded to GPU buffers.
void load (VK_Window *window, const std::string &modelPath, const std::string &textureManifestPath, const std::string &textureBasePath, float scale=1.0f)
 Load mesh/texture resources and build Vulkan state.
void load (VK_Window *window, MXModel &&model, const std::string &textureManifestPath, const std::string &textureBasePath, float scale=1.0f)
 Consume pre-parsed mesh data and build Vulkan state.
const MXModelmodel () const
 Access the underlying mesh object.
glm::vec3 modelAxisExtent () const
 Per-axis extent (max - min) of the source mesh's bounding box.
glm::vec3 modelCenterOffset () const
 Access the computed center offset used for normalization.
float modelRenderScale () const
 Access the computed render scale used for normalization.
VKAbstractModeloperator= (const VKAbstractModel &)=delete
VKAbstractModeloperator= (VKAbstractModel &&)=delete
void render (VkCommandBuffer cmd, uint32_t imageIndex, bool wireframe=false) const
 Record draw commands for this model.
void renderWithExternalTexture (VkCommandBuffer cmd, uint32_t imageIndex, VkImageView textureView, const UniformBufferObject &ubo, bool wireframe=false)
 Render using a non-owning shader-readable image view as texture slot zero.
void renderWithPushConstants (VkCommandBuffer cmd, uint32_t imageIndex, size_t textureIndex, const UniformBufferObject &ubo, bool wireframe=false)
 Record one draw using push constants for per-draw transforms and an explicit texture slot.
void resize (VK_Window *window)
 Rebuild swapchain-dependent resources after resize.
void setAlphaBlending (bool enabled)
 Enable or disable alpha blending for this model pipeline.
void setBackfaceCulling (bool enabled)
 Enable or disable backface culling for this model pipeline.
void setFragmentPushConstants (const ModelFragmentPushConstants &constants)
 Set sprite-compatible push constants used by custom fragment shaders.
void setShaders (VK_Window *window, const std::string &vertSpv, const std::string &fragSpv)
 Configure custom shader paths and rebuild pipelines.
void updateFragmentUBO (uint32_t imageIndex, const ModelFragmentUniforms &uniforms)
 Update extended fragment uniforms for one swapchain image.
bool updatePrimaryTexture (const void *pixels, int width, int height, int pitch=0)
 Upload raw RGBA pixels into the primary model texture.
void updateUBO (uint32_t imageIndex, const UniformBufferObject &ubo)
 Update one per-frame UBO payload.
 VKAbstractModel ()=default
 VKAbstractModel (const VKAbstractModel &)=delete
 VKAbstractModel (VKAbstractModel &&)=delete
 ~VKAbstractModel ()=default

Detailed Description

Convenience wrapper that owns mesh, textures, descriptors, and pipeline state.

This class is intended to be recorded from inside VK_Window::onRecordCustomRendering() so it participates in the same dynamic-rendering pass as sprites/text.

Definition at line 71 of file mxvk_abstract_model.hpp.

Constructor & Destructor Documentation

◆ VKAbstractModel() [1/3]

mxvk::VKAbstractModel::VKAbstractModel ( )
default

◆ ~VKAbstractModel()

mxvk::VKAbstractModel::~VKAbstractModel ( )
default

◆ VKAbstractModel() [2/3]

mxvk::VKAbstractModel::VKAbstractModel ( const VKAbstractModel & )
delete

◆ VKAbstractModel() [3/3]

mxvk::VKAbstractModel::VKAbstractModel ( VKAbstractModel && )
delete

Member Function Documentation

◆ cleanup()

void mxvk::VKAbstractModel::cleanup ( VK_Window * window)

Destroy all owned Vulkan resources.

Parameters
windowActive MXVK window.

Definition at line 511 of file mxvk_abstract_model.cpp.

511 {
512 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
513 return;
514 }
515
516 logVKAbstractModelStep("teardown begin", true);
517 windowPtr = targetWindow;
518 destroyPipelines();
519 destroyDescriptors();
520 destroyTextures();
521 obj.cleanup(windowPtr->getDevice());
522 windowPtr = nullptr;
523 logVKAbstractModelStep("teardown complete", true);
524 }
void logVKAbstractModelStep(const std::string &message, bool important=false)

◆ enableExtendedFragmentUniforms()

void mxvk::VKAbstractModel::enableExtendedFragmentUniforms ( )

Use binding 1 for fragment uniforms and binding 2 for model transforms.

Call before load().

Definition at line 214 of file mxvk_abstract_model.cpp.

214 {
215 if (windowPtr != nullptr) {
216 throw mxvk::Exception("VKAbstractModel::enableExtendedFragmentUniforms must be called before load");
217 }
218 extendedFragmentUniformsEnabled = true;
219 }

◆ isLoaded()

bool mxvk::VKAbstractModel::isLoaded ( ) const
inlinenodiscard

True once the model has been uploaded to GPU buffers.

Definition at line 203 of file mxvk_abstract_model.hpp.

203{ return obj.indexCount() > 0 && vertexBufferReady(); }

◆ load() [1/2]

void mxvk::VKAbstractModel::load ( VK_Window * window,
const std::string & modelPath,
const std::string & textureManifestPath,
const std::string & textureBasePath,
float scale = 1.0f )

Load mesh/texture resources and build Vulkan state.

Parameters
windowActive MXVK window.
modelPathPath to .obj or .mxmod mesh file.
textureManifestPathOptional texture manifest path (.tex or .mtl-like text).
textureBasePathOptional base path for texture files in the manifest.
scaleUniform mesh scale.

Definition at line 81 of file mxvk_abstract_model.cpp.

85 {
86 if (targetWindow == nullptr) {
87 throw mxvk::Exception("VKAbstractModel::load requires a valid window");
88 }
89 if (modelPath.empty()) {
90 throw mxvk::Exception("VKAbstractModel::load modelPath is empty");
91 }
92
93 logVKAbstractModelStep("creation begin: " + modelPath, true);
94
95 windowPtr = targetWindow;
96 if (!windowPtr->ensureRenderResources()) {
97 throw mxvk::Exception("VKAbstractModel::load failed because render resources are not ready");
98 }
99
100 obj.load(modelPath, scale);
101 obj.upload(windowPtr->getDevice(), windowPtr->getPhysicalDevice(), windowPtr->getCommandPool(), windowPtr->getGraphicsQueue());
102 computeBoundsAndScale();
103 logVKAbstractModelStep("mesh upload complete", true);
104
105 textures.clear();
106 if (!textureManifestPath.empty()) {
107 loadTextures(textureManifestPath, textureBasePath);
108 } else {
109 loadTexturesFromMTL(textureBasePath.empty() ? std::filesystem::path(modelPath).parent_path().string() : textureBasePath);
110 }
111 if (textures.empty()) {
112 createFallbackTexture();
113 logVKAbstractModelStep("using fallback texture", true);
114 }
115 logVKAbstractModelStep("textures ready: " + std::to_string(textures.size()), true);
116
117 createTextureSampler();
118 createDescriptorSetLayout();
119 createUniformBuffers();
120 createDescriptorPool();
121 createDescriptorSets();
122 createPipelines();
123 logVKAbstractModelStep("creation complete", true);
124 }

◆ load() [2/2]

void mxvk::VKAbstractModel::load ( VK_Window * window,
MXModel && model,
const std::string & textureManifestPath,
const std::string & textureBasePath,
float scale = 1.0f )

Consume pre-parsed mesh data and build Vulkan state.

Parameters
windowActive MXVK window.
modelPre-parsed CPU-side model data.
textureManifestPathOptional texture manifest path (.tex or .mtl-like text).
textureBasePathOptional base path for texture files in the manifest.
scaleUniform mesh scale. Kept for API compatibility.

Definition at line 126 of file mxvk_abstract_model.cpp.

130 {
131 if (targetWindow == nullptr) {
132 throw mxvk::Exception("VKAbstractModel::load requires a valid window");
133 }
134
135 windowPtr = targetWindow;
136 if (!windowPtr->ensureRenderResources()) {
137 throw mxvk::Exception("VKAbstractModel::load failed because render resources are not ready");
138 }
139
140 obj = std::move(model);
141 obj.upload(windowPtr->getDevice(), windowPtr->getPhysicalDevice(), windowPtr->getCommandPool(), windowPtr->getGraphicsQueue());
142 computeBoundsAndScale();
143 logVKAbstractModelStep("mesh upload complete (prepared)", true);
144
145 textures.clear();
146 if (!textureManifestPath.empty()) {
147 loadTextures(textureManifestPath, textureBasePath);
148 } else if (!obj.mtlLibPath().empty()) {
149 loadTexturesFromMTL(textureBasePath.empty() ? std::filesystem::path(obj.mtlLibPath()).parent_path().string() : textureBasePath);
150 } else {
151 createFallbackTexture();
152 logVKAbstractModelStep("using fallback texture", true);
153 }
154 if (textures.empty()) {
155 createFallbackTexture();
156 logVKAbstractModelStep("using fallback texture", true);
157 }
158 logVKAbstractModelStep("textures ready: " + std::to_string(textures.size()), true);
159
160 createTextureSampler();
161 createDescriptorSetLayout();
162 createUniformBuffers();
163 createDescriptorPool();
164 createDescriptorSets();
165 createPipelines();
166 logVKAbstractModelStep("creation complete", true);
167 }
const MXModel & model() const
Access the underlying mesh object.

◆ model()

const MXModel & mxvk::VKAbstractModel::model ( ) const
inlinenodiscard

Access the underlying mesh object.

Definition at line 195 of file mxvk_abstract_model.hpp.

195{ return obj; }

◆ modelAxisExtent()

glm::vec3 mxvk::VKAbstractModel::modelAxisExtent ( ) const
inlinenodiscard

Per-axis extent (max - min) of the source mesh's bounding box.

Definition at line 201 of file mxvk_abstract_model.hpp.

201{ return modelAxisExtentValue; }

◆ modelCenterOffset()

glm::vec3 mxvk::VKAbstractModel::modelCenterOffset ( ) const
inlinenodiscard

Access the computed center offset used for normalization.

Definition at line 197 of file mxvk_abstract_model.hpp.

197{ return modelCenterOffsetValue; }

◆ modelRenderScale()

float mxvk::VKAbstractModel::modelRenderScale ( ) const
inlinenodiscard

Access the computed render scale used for normalization.

Definition at line 199 of file mxvk_abstract_model.hpp.

199{ return modelRenderScaleValue; }

◆ operator=() [1/2]

VKAbstractModel & mxvk::VKAbstractModel::operator= ( const VKAbstractModel & )
delete

◆ operator=() [2/2]

VKAbstractModel & mxvk::VKAbstractModel::operator= ( VKAbstractModel && )
delete

◆ render()

void mxvk::VKAbstractModel::render ( VkCommandBuffer cmd,
uint32_t imageIndex,
bool wireframe = false ) const

Record draw commands for this model.

Parameters
cmdActive command buffer, inside a dynamic rendering scope.
imageIndexCurrent swapchain image index.
wireframeRender using the optional wireframe pipeline when available.

Definition at line 345 of file mxvk_abstract_model.cpp.

345 {
346 if (cmd == VK_NULL_HANDLE || imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
347 return;
348 }
349
350 const VkPipeline pipeline = (wireframe && pipelineWireframe != VK_NULL_HANDLE) ? pipelineWireframe : pipelineFill;
351 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
352 return;
353 }
354
355 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
356 if (extendedFragmentUniformsEnabled) {
357 vkCmdPushConstants(cmd,
358 pipelineLayout,
359 VK_SHADER_STAGE_FRAGMENT_BIT,
360 0,
361 sizeof(ModelFragmentPushConstants),
362 &fragmentPushConstants);
363 }
364
365 const size_t textureCount = std::max<size_t>(1, textures.size());
366 for (size_t i = 0; i < obj.subMeshCount(); ++i) {
367 const SubMesh &submesh = obj.subMesh(i);
368 const size_t textureIndex = std::min<size_t>(submesh.textureIndex, textureCount - 1U);
369 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount + textureIndex;
370 if (setIndex >= descriptorSets.size()) {
371 continue;
372 }
373
374 vkCmdBindDescriptorSets(cmd,
375 VK_PIPELINE_BIND_POINT_GRAPHICS,
376 pipelineLayout,
377 0,
378 1,
379 &descriptorSets[setIndex],
380 0,
381 nullptr);
382
383 obj.drawSubMesh(cmd, i);
384 }
385 }

◆ renderWithExternalTexture()

void mxvk::VKAbstractModel::renderWithExternalTexture ( VkCommandBuffer cmd,
uint32_t imageIndex,
VkImageView textureView,
const UniformBufferObject & ubo,
bool wireframe = false )

Render using a non-owning shader-readable image view as texture slot zero.

Definition at line 444 of file mxvk_abstract_model.cpp.

446 {
447 if (cmd == VK_NULL_HANDLE || textureView == VK_NULL_HANDLE ||
448 imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
449 return;
450 }
451
452 const VkPipeline pipeline =
453 (wireframe && pipelineWireframe != VK_NULL_HANDLE)
454 ? pipelineWireframe
455 : pipelineFill;
456 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
457 return;
458 }
459
460 const size_t textureCount = std::max<size_t>(1, textures.size());
461 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount;
462 if (setIndex >= descriptorSets.size()) {
463 return;
464 }
465 updateTextureDescriptor(descriptorSets[setIndex], textureView);
466
467 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
468 updateUBO(imageIndex, ubo);
469 if (!extendedFragmentUniformsEnabled) {
470 const ModelPushConstants pushConstants{
471 .model = ubo.model,
472 .fx = ubo.fx,
473 };
474 vkCmdPushConstants(cmd, pipelineLayout,
475 VK_SHADER_STAGE_VERTEX_BIT, 0,
476 sizeof(ModelPushConstants), &pushConstants);
477 }
478 if (extendedFragmentUniformsEnabled) {
479 vkCmdPushConstants(cmd, pipelineLayout,
480 VK_SHADER_STAGE_FRAGMENT_BIT, 0,
481 sizeof(ModelFragmentPushConstants),
482 &fragmentPushConstants);
483 }
484 vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
485 pipelineLayout, 0, 1,
486 &descriptorSets[setIndex], 0, nullptr);
487 obj.draw(cmd);
488 }
void updateUBO(uint32_t imageIndex, const UniformBufferObject &ubo)
Update one per-frame UBO payload.

◆ renderWithPushConstants()

void mxvk::VKAbstractModel::renderWithPushConstants ( VkCommandBuffer cmd,
uint32_t imageIndex,
size_t textureIndex,
const UniformBufferObject & ubo,
bool wireframe = false )

Record one draw using push constants for per-draw transforms and an explicit texture slot.

Parameters
cmdActive command buffer, inside a dynamic rendering scope.
imageIndexCurrent swapchain image index.
textureIndexTexture slot to bind for all submeshes in this draw.
uboTransform/effect payload copied into vertex-stage push constants.
wireframeRender using the optional wireframe pipeline when available.

Definition at line 387 of file mxvk_abstract_model.cpp.

391 {
392 if (cmd == VK_NULL_HANDLE || imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
393 return;
394 }
395
396 const VkPipeline pipeline = (wireframe && pipelineWireframe != VK_NULL_HANDLE) ? pipelineWireframe : pipelineFill;
397 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
398 return;
399 }
400
401 const size_t textureCount = std::max<size_t>(1, textures.size());
402 textureIndex = std::min(textureIndex, textureCount - 1U);
403 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount + textureIndex;
404 if (setIndex >= descriptorSets.size()) {
405 return;
406 }
407 updateTextureDescriptor(descriptorSets[setIndex],
408 textures[textureIndex].view);
409
410 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
411 updateUBO(imageIndex, ubo);
412 if (!extendedFragmentUniformsEnabled) {
413 const ModelPushConstants pushConstants{
414 .model = ubo.model,
415 .fx = ubo.fx,
416 };
417 vkCmdPushConstants(cmd,
418 pipelineLayout,
419 VK_SHADER_STAGE_VERTEX_BIT,
420 0,
421 sizeof(ModelPushConstants),
422 &pushConstants);
423 }
424 if (extendedFragmentUniformsEnabled) {
425 vkCmdPushConstants(cmd,
426 pipelineLayout,
427 VK_SHADER_STAGE_FRAGMENT_BIT,
428 0,
429 sizeof(ModelFragmentPushConstants),
430 &fragmentPushConstants);
431 }
432 vkCmdBindDescriptorSets(cmd,
433 VK_PIPELINE_BIND_POINT_GRAPHICS,
434 pipelineLayout,
435 0,
436 1,
437 &descriptorSets[setIndex],
438 0,
439 nullptr);
440
441 obj.draw(cmd);
442 }

◆ resize()

void mxvk::VKAbstractModel::resize ( VK_Window * window)

Rebuild swapchain-dependent resources after resize.

Parameters
windowActive MXVK window.

Definition at line 490 of file mxvk_abstract_model.cpp.

490 {
491 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
492 return;
493 }
494 if (!isLoaded()) {
495 return;
496 }
497
498 logVKAbstractModelStep("resize begin", true);
499 windowPtr = targetWindow;
500 destroyPipelines();
501 destroyDescriptors();
502
503 createDescriptorSetLayout();
504 createUniformBuffers();
505 createDescriptorPool();
506 createDescriptorSets();
507 createPipelines();
508 logVKAbstractModelStep("resize complete", true);
509 }
bool isLoaded() const
True once the model has been uploaded to GPU buffers.

◆ setAlphaBlending()

void mxvk::VKAbstractModel::setAlphaBlending ( bool enabled)

Enable or disable alpha blending for this model pipeline.

Parameters
enabledTrue to blend fragment alpha and avoid depth writes.

Definition at line 192 of file mxvk_abstract_model.cpp.

192 {
193 if (alphaBlendingEnabled == enabled) {
194 return;
195 }
196
197 alphaBlendingEnabled = enabled;
198 if (windowPtr != nullptr) {
199 createPipelines();
200 }
201 }

◆ setBackfaceCulling()

void mxvk::VKAbstractModel::setBackfaceCulling ( bool enabled)

Enable or disable backface culling for this model pipeline.

Parameters
enabledTrue to cull backfaces, false to disable culling.

Definition at line 181 of file mxvk_abstract_model.cpp.

181 {
182 if (backfaceCullingEnabled == enabled) {
183 return;
184 }
185
186 backfaceCullingEnabled = enabled;
187 if (windowPtr != nullptr) {
188 createPipelines();
189 }
190 }

◆ setFragmentPushConstants()

void mxvk::VKAbstractModel::setFragmentPushConstants ( const ModelFragmentPushConstants & constants)

Set sprite-compatible push constants used by custom fragment shaders.

Definition at line 228 of file mxvk_abstract_model.cpp.

228 {
229 fragmentPushConstants = constants;
230 }

◆ setShaders()

void mxvk::VKAbstractModel::setShaders ( VK_Window * window,
const std::string & vertSpv,
const std::string & fragSpv )

Configure custom shader paths and rebuild pipelines.

Parameters
windowActive MXVK window.
vertSpvVertex shader SPIR-V path.
fragSpvFragment shader SPIR-V path.

Definition at line 169 of file mxvk_abstract_model.cpp.

169 {
170 if (targetWindow == nullptr) {
171 throw mxvk::Exception("VKAbstractModel::setShaders requires a valid window");
172 }
173
174 windowPtr = targetWindow;
175 vertexShaderPath = vertSpv;
176 fragmentShaderPath = fragSpv;
177 logVKAbstractModelStep("setShaders", true);
178 createPipelines();
179 }

◆ updateFragmentUBO()

void mxvk::VKAbstractModel::updateFragmentUBO ( uint32_t imageIndex,
const ModelFragmentUniforms & uniforms )

Update extended fragment uniforms for one swapchain image.

Definition at line 221 of file mxvk_abstract_model.cpp.

221 {
222 if (imageIndex >= fragmentUniformBuffersMapped.size() || fragmentUniformBuffersMapped[imageIndex] == nullptr) {
223 return;
224 }
225 std::memcpy(fragmentUniformBuffersMapped[imageIndex], &uniforms, sizeof(ModelFragmentUniforms));
226 }

◆ updatePrimaryTexture()

bool mxvk::VKAbstractModel::updatePrimaryTexture ( const void * pixels,
int width,
int height,
int pitch = 0 )
nodiscard

Upload raw RGBA pixels into the primary model texture.

Parameters
pixelsPointer to RGBA8 pixel data.
widthTexture width in pixels.
heightTexture height in pixels.
pitchBytes per input row. When 0, defaults to width * 4.
Returns
True when the upload succeeds, false for invalid inputs or unavailable resources.

Definition at line 232 of file mxvk_abstract_model.cpp.

232 {
233 if (windowPtr == nullptr || windowPtr->getDevice() == VK_NULL_HANDLE) {
234 return false;
235 }
236 if (pixels == nullptr || width <= 0 || height <= 0) {
237 return false;
238 }
239
240 const uint32_t uploadWidth = static_cast<uint32_t>(width);
241 const uint32_t uploadHeight = static_cast<uint32_t>(height);
242 const uint32_t srcRowBytes = static_cast<uint32_t>(pitch > 0 ? pitch : width * 4);
243 const uint32_t tightRowBytes = uploadWidth * 4U;
244 if (srcRowBytes < tightRowBytes) {
245 return false;
246 }
247
248 if (textures.empty()) {
249 createFallbackTexture();
250 createDescriptorSets();
251 }
252
253 TextureEntry &texture = textures[0];
254 if (texture.image == VK_NULL_HANDLE || texture.memory == VK_NULL_HANDLE || texture.view == VK_NULL_HANDLE) {
255 return false;
256 }
257
258 bool recreatedTexture = false;
259 if (texture.width != uploadWidth || texture.height != uploadHeight) {
260 vkDeviceWaitIdle(windowPtr->getDevice());
261
262#ifdef MXVK_CUDA
263 destroyTextureCudaInterop(texture);
264#endif
265 if (texture.view != VK_NULL_HANDLE) {
266 vkDestroyImageView(windowPtr->getDevice(), texture.view, nullptr);
267 }
268 if (texture.image != VK_NULL_HANDLE) {
269 vkDestroyImage(windowPtr->getDevice(), texture.image, nullptr);
270 }
271 if (texture.memory != VK_NULL_HANDLE) {
272 vkFreeMemory(windowPtr->getDevice(), texture.memory, nullptr);
273 }
274
275 texture.view = VK_NULL_HANDLE;
276 texture.image = VK_NULL_HANDLE;
277 texture.memory = VK_NULL_HANDLE;
278
279 createTextureImage(uploadWidth, uploadHeight, texture);
280
281 texture.view = createImageView(texture.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
282 texture.width = uploadWidth;
283 texture.height = uploadHeight;
284 recreatedTexture = true;
285
286 createDescriptorSets();
287 }
288
289#ifdef MXVK_CUDA
290 if (updatePrimaryTextureCudaHost(texture, pixels, uploadWidth, uploadHeight, srcRowBytes)) {
291 return true;
292 }
293#endif
294
295 const VkDeviceSize stagingSize = static_cast<VkDeviceSize>(tightRowBytes) * uploadHeight;
296 VkBuffer stagingBuffer = VK_NULL_HANDLE;
297 VkDeviceMemory stagingMemory = VK_NULL_HANDLE;
298 createBuffer(stagingSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
299 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
300 stagingBuffer, stagingMemory);
301
302 void *mapped = nullptr;
303 const VkResult mapResult = vkMapMemory(windowPtr->getDevice(), stagingMemory, 0, stagingSize, 0, &mapped);
304 if (mapResult != VK_SUCCESS || mapped == nullptr) {
305 vkDestroyBuffer(windowPtr->getDevice(), stagingBuffer, nullptr);
306 vkFreeMemory(windowPtr->getDevice(), stagingMemory, nullptr);
307 return false;
308 }
309
310 if (srcRowBytes == tightRowBytes) {
311 std::memcpy(mapped, pixels, static_cast<size_t>(stagingSize));
312 } else {
313 const auto *src = static_cast<const uint8_t *>(pixels);
314 auto *dst = static_cast<uint8_t *>(mapped);
315 for (uint32_t y = 0; y < uploadHeight; ++y) {
316 const size_t srcOffset = static_cast<size_t>(y) * srcRowBytes;
317 const size_t dstOffset = static_cast<size_t>(y) * tightRowBytes;
318 std::memcpy(dst + dstOffset, src + srcOffset, tightRowBytes);
319 }
320 }
321 vkUnmapMemory(windowPtr->getDevice(), stagingMemory);
322
323 if (recreatedTexture) {
324 transitionImageLayout(texture.image, VK_FORMAT_R8G8B8A8_UNORM,
325 VK_IMAGE_LAYOUT_UNDEFINED,
326 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
327 } else {
328 transitionImageLayout(texture.image, VK_FORMAT_R8G8B8A8_UNORM,
329 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
330 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
331 }
332 copyBufferToImage(stagingBuffer, texture.image, uploadWidth, uploadHeight);
333 transitionImageLayout(texture.image, VK_FORMAT_R8G8B8A8_UNORM,
334 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
335 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
336#ifdef MXVK_CUDA
337 texture.cudaImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
338#endif
339
340 vkDestroyBuffer(windowPtr->getDevice(), stagingBuffer, nullptr);
341 vkFreeMemory(windowPtr->getDevice(), stagingMemory, nullptr);
342 return true;
343 }

◆ updateUBO()

void mxvk::VKAbstractModel::updateUBO ( uint32_t imageIndex,
const UniformBufferObject & ubo )

Update one per-frame UBO payload.

Parameters
imageIndexSwapchain image index.
uboNew transform values.

Definition at line 203 of file mxvk_abstract_model.cpp.

203 {
204 if (imageIndex >= uniformBuffersMapped.size()) {
205 return;
206 }
207 if (uniformBuffersMapped[imageIndex] == nullptr) {
208 return;
209 }
210
211 std::memcpy(uniformBuffersMapped[imageIndex], &ubo, sizeof(UniformBufferObject));
212 }

The documentation for this class was generated from the following files: