MXVK Vulkan Framework 0.35.0
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 MXModel & model () 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.
VKAbstractModel & operator= (const VKAbstractModel &)=delete
VKAbstractModel & operator= (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 setColorAttachmentFormat (VkFormat format)
 Override the dynamic-rendering color format for this model.
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 455 of file mxvk_abstract_model.cpp.

455 {
456 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
457 return;
458 }
459
460 logVKAbstractModelStep("teardown begin", true);
461 windowPtr = targetWindow;
462 destroyPipelines();
463 destroyDescriptors();
464 destroyTextures();
465 obj.cleanup(windowPtr->getDevice());
466 windowPtr = nullptr;
467 logVKAbstractModelStep("teardown complete", true);
468 }
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 215 of file mxvk_abstract_model.cpp.

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

◆ isLoaded()

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

True once the model has been uploaded to GPU buffers.

Definition at line 187 of file mxvk_abstract_model.hpp.

187{ 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 80 of file mxvk_abstract_model.cpp.

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

◆ 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 121 of file mxvk_abstract_model.cpp.

121 {
122 if (targetWindow == nullptr) {
123 throw mxvk::Exception("VKAbstractModel::load requires a valid window");
124 }
125
126 windowPtr = targetWindow;
127 if (!windowPtr->ensureRenderResources()) {
128 throw mxvk::Exception("VKAbstractModel::load failed because render resources are not ready");
129 }
130
131 obj = std::move(model);
132 obj.upload(windowPtr->getDevice(), windowPtr->getPhysicalDevice(), windowPtr->getCommandPool(), windowPtr->getGraphicsQueue());
133 computeBoundsAndScale();
134 logVKAbstractModelStep("mesh upload complete (prepared)", true);
135
136 textures.clear();
137 if (!textureManifestPath.empty()) {
138 loadTextures(textureManifestPath, textureBasePath);
139 } else if (!obj.mtlLibPath().empty()) {
140 loadTexturesFromMTL(textureBasePath.empty() ? std::filesystem::path(obj.mtlLibPath()).parent_path().string() : textureBasePath);
141 } else {
142 createFallbackTexture();
143 logVKAbstractModelStep("using fallback texture", true);
144 }
145 if (textures.empty()) {
146 createFallbackTexture();
147 logVKAbstractModelStep("using fallback texture", true);
148 }
149 logVKAbstractModelStep("textures ready: " + std::to_string(textures.size()), true);
150
151 createTextureSampler();
152 createDescriptorSetLayout();
153 createUniformBuffers();
154 createDescriptorPool();
155 createDescriptorSets();
156 createPipelines();
157 logVKAbstractModelStep("creation complete", true);
158 }
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 179 of file mxvk_abstract_model.hpp.

179{ 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 185 of file mxvk_abstract_model.hpp.

185{ return modelAxisExtentValue; }

◆ modelCenterOffset()

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

Access the computed center offset used for normalization.

Definition at line 181 of file mxvk_abstract_model.hpp.

181{ return modelCenterOffsetValue; }

◆ modelRenderScale()

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

Access the computed render scale used for normalization.

Definition at line 183 of file mxvk_abstract_model.hpp.

183{ 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 336 of file mxvk_abstract_model.cpp.

336 {
337 if (cmd == VK_NULL_HANDLE || imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
338 return;
339 }
340
341 const VkPipeline pipeline = (wireframe && pipelineWireframe != VK_NULL_HANDLE) ? pipelineWireframe : pipelineFill;
342 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
343 return;
344 }
345
346 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
347 if (extendedFragmentUniformsEnabled) {
348 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ModelFragmentPushConstants), &fragmentPushConstants);
349 }
350
351 const size_t textureCount = std::max<size_t>(1, textures.size());
352 for (size_t i = 0; i < obj.subMeshCount(); ++i) {
353 const SubMesh &submesh = obj.subMesh(i);
354 const size_t textureIndex = std::min<size_t>(submesh.textureIndex, textureCount - 1U);
355 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount + textureIndex;
356 if (setIndex >= descriptorSets.size()) {
357 continue;
358 }
359
360 vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[setIndex], 0, nullptr);
361
362 obj.drawSubMesh(cmd, i);
363 }
364 }

◆ 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 401 of file mxvk_abstract_model.cpp.

401 {
402 if (cmd == VK_NULL_HANDLE || textureView == VK_NULL_HANDLE || imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
403 return;
404 }
405
406 const VkPipeline pipeline = (wireframe && pipelineWireframe != VK_NULL_HANDLE) ? pipelineWireframe : pipelineFill;
407 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
408 return;
409 }
410
411 const size_t textureCount = std::max<size_t>(1, textures.size());
412 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount;
413 if (setIndex >= descriptorSets.size()) {
414 return;
415 }
416 updateTextureDescriptor(descriptorSets[setIndex], textureView);
417
418 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
419 updateUBO(imageIndex, ubo);
420 if (!extendedFragmentUniformsEnabled) {
421 const ModelPushConstants pushConstants{
422 .model = ubo.model,
423 .fx = ubo.fx,
424 };
425 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ModelPushConstants), &pushConstants);
426 }
427 if (extendedFragmentUniformsEnabled) {
428 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ModelFragmentPushConstants), &fragmentPushConstants);
429 }
430 vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[setIndex], 0, nullptr);
431 obj.draw(cmd);
432 }
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 366 of file mxvk_abstract_model.cpp.

366 {
367 if (cmd == VK_NULL_HANDLE || imageIndex >= uniformBuffers.size() || descriptorSets.empty()) {
368 return;
369 }
370
371 const VkPipeline pipeline = (wireframe && pipelineWireframe != VK_NULL_HANDLE) ? pipelineWireframe : pipelineFill;
372 if (pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
373 return;
374 }
375
376 const size_t textureCount = std::max<size_t>(1, textures.size());
377 textureIndex = std::min(textureIndex, textureCount - 1U);
378 const size_t setIndex = static_cast<size_t>(imageIndex) * textureCount + textureIndex;
379 if (setIndex >= descriptorSets.size()) {
380 return;
381 }
382 updateTextureDescriptor(descriptorSets[setIndex], textures[textureIndex].view);
383
384 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
385 updateUBO(imageIndex, ubo);
386 if (!extendedFragmentUniformsEnabled) {
387 const ModelPushConstants pushConstants{
388 .model = ubo.model,
389 .fx = ubo.fx,
390 };
391 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ModelPushConstants), &pushConstants);
392 }
393 if (extendedFragmentUniformsEnabled) {
394 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ModelFragmentPushConstants), &fragmentPushConstants);
395 }
396 vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[setIndex], 0, nullptr);
397
398 obj.draw(cmd);
399 }

◆ resize()

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

Rebuild swapchain-dependent resources after resize.

Parameters
windowActive MXVK window.

Definition at line 434 of file mxvk_abstract_model.cpp.

434 {
435 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
436 return;
437 }
438 if (!isLoaded()) {
439 return;
440 }
441
442 logVKAbstractModelStep("resize begin", true);
443 windowPtr = targetWindow;
444 destroyPipelines();
445 destroyDescriptors();
446
447 createDescriptorSetLayout();
448 createUniformBuffers();
449 createDescriptorPool();
450 createDescriptorSets();
451 createPipelines();
452 logVKAbstractModelStep("resize complete", true);
453 }
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 183 of file mxvk_abstract_model.cpp.

183 {
184 if (alphaBlendingEnabled == enabled) {
185 return;
186 }
187
188 alphaBlendingEnabled = enabled;
189 if (windowPtr != nullptr) {
190 createPipelines();
191 }
192 }

◆ 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 172 of file mxvk_abstract_model.cpp.

172 {
173 if (backfaceCullingEnabled == enabled) {
174 return;
175 }
176
177 backfaceCullingEnabled = enabled;
178 if (windowPtr != nullptr) {
179 createPipelines();
180 }
181 }

◆ setColorAttachmentFormat()

void mxvk::VKAbstractModel::setColorAttachmentFormat ( VkFormat format)

Override the dynamic-rendering color format for this model.

Definition at line 194 of file mxvk_abstract_model.cpp.

194 {
195 if (colorAttachmentFormat == format) {
196 return;
197 }
198 colorAttachmentFormat = format;
199 if (windowPtr != nullptr) {
200 createPipelines();
201 }
202 }

◆ setFragmentPushConstants()

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

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

Definition at line 229 of file mxvk_abstract_model.cpp.

229{ fragmentPushConstants = constants; }

◆ 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 160 of file mxvk_abstract_model.cpp.

160 {
161 if (targetWindow == nullptr) {
162 throw mxvk::Exception("VKAbstractModel::setShaders requires a valid window");
163 }
164
165 windowPtr = targetWindow;
166 vertexShaderPath = vertSpv;
167 fragmentShaderPath = fragSpv;
168 logVKAbstractModelStep("setShaders", true);
169 createPipelines();
170 }

◆ updateFragmentUBO()

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

Update extended fragment uniforms for one swapchain image.

Definition at line 222 of file mxvk_abstract_model.cpp.

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

◆ 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 231 of file mxvk_abstract_model.cpp.

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

◆ 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 204 of file mxvk_abstract_model.cpp.

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

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