@@ -209,11 +209,12 @@ void CommandEncoder::write_buffer(const std::shared_ptr<Buffer> &buffer,
209209 return ;
210210 }
211211
212- // Write buffer by memory mapping.
213- if (buffer->get_memory_property () == MemoryProperty::HostVisibleAndCoherent) {
214- buffer->upload_via_mapping (data_size, offset, data);
215- return ;
216- }
212+ auto device = device_.lock ();
213+ auto allocation = device->allocate_staging (data_size);
214+
215+ void *mapped_ptr = device->map_staging (allocation);
216+ memcpy (mapped_ptr, data, data_size);
217+ device->unmap_staging (allocation);
217218
218219 Command cmd{};
219220 cmd.type = CommandType::WriteBuffer;
@@ -222,9 +223,12 @@ void CommandEncoder::write_buffer(const std::shared_ptr<Buffer> &buffer,
222223 args.buffer = buffer.get ();
223224 args.offset = offset;
224225 args.data_size = data_size;
225- args.data = data;
226+ args.staging_buffer = allocation.buffer .get ();
227+ args.staging_offset = (uint32_t )allocation.offset ;
226228
227229 commands_.push_back (cmd);
230+
231+ track_temporary_resource (allocation.buffer );
228232}
229233
230234void CommandEncoder::read_buffer (const std::shared_ptr<Buffer> &buffer,
@@ -238,15 +242,12 @@ void CommandEncoder::read_buffer(const std::shared_ptr<Buffer> &buffer,
238242
239243 if (data_size == 0 || data == nullptr ) {
240244 Logger::error (" Tried to read invalid data from buffer!" );
241- }
242-
243- // Read buffer by memory mapping.
244- if (buffer->get_memory_property () == MemoryProperty::HostVisibleAndCoherent) {
245- Logger::error (" You're trying to read a mappable buffer through a command. It may indicate some bug." );
246- buffer->download_via_mapping (data_size, offset, data);
247245 return ;
248246 }
249247
248+ auto device = device_.lock ();
249+ auto allocation = device->allocate_staging (data_size);
250+
250251 Command cmd{};
251252 cmd.type = CommandType::ReadBuffer;
252253
@@ -255,22 +256,40 @@ void CommandEncoder::read_buffer(const std::shared_ptr<Buffer> &buffer,
255256 args.offset = offset;
256257 args.data_size = data_size;
257258 args.data = data;
259+ args.staging_buffer = allocation.buffer .get ();
260+ args.staging_offset = (uint32_t )allocation.offset ;
258261
259262 commands_.push_back (cmd);
263+
264+ add_callback ([allocation, data, data_size, device] {
265+ void *mapped_ptr = device->map_staging (allocation);
266+ memcpy (data, mapped_ptr, data_size);
267+ device->unmap_staging (allocation);
268+ });
269+
270+ track_temporary_resource (allocation.buffer );
260271}
261272
262273void CommandEncoder::write_texture (const std::shared_ptr<Texture> &texture, RectI region, const void *src) {
263274 auto whole_region = RectI ({0 , 0 }, {texture->get_size ()});
264275
265- // Invalid region represents the whole texture.
266276 auto effective_region = region.is_valid () ? region : whole_region;
267277
268- // Check if the region is a subset of the whole texture region.
269278 if (!effective_region.union_rect (whole_region).is_valid () || effective_region.area () == 0 ) {
270279 Logger::error (" Tried to write invalid region of a texture!" );
271280 return ;
272281 }
273282
283+ auto pixel_size = get_pixel_size (texture->get_format ());
284+ size_t data_size = (size_t )effective_region.width () * effective_region.height () * pixel_size;
285+
286+ auto device = device_.lock ();
287+ auto allocation = device->allocate_staging (data_size);
288+
289+ void *mapped_ptr = device->map_staging (allocation);
290+ memcpy (mapped_ptr, src, data_size);
291+ device->unmap_staging (allocation);
292+
274293 Command cmd{};
275294 cmd.type = CommandType::WriteTexture;
276295
@@ -280,23 +299,30 @@ void CommandEncoder::write_texture(const std::shared_ptr<Texture> &texture, Rect
280299 args.offset_y = effective_region.top ;
281300 args.width = effective_region.width ();
282301 args.height = effective_region.height ();
283- args.data = src;
302+ args.staging_buffer = allocation.buffer .get ();
303+ args.staging_offset = (uint32_t )allocation.offset ;
284304
285305 commands_.push_back (cmd);
306+
307+ track_temporary_resource (allocation.buffer );
286308}
287309
288310void CommandEncoder::read_texture (const std::shared_ptr<Texture> &texture, RectI region, void *dst) {
289311 auto whole_region = RectI ({0 , 0 }, {texture->get_size ()});
290312
291- // Invalid region represents the whole texture.
292313 auto effective_region = region.is_valid () ? region : whole_region;
293314
294- // Check if the region is a subset of the whole texture region.
295315 if (!effective_region.union_rect (whole_region).is_valid () || effective_region.area () == 0 ) {
296316 Logger::error (" Tried to write invalid region of a texture!" );
297317 return ;
298318 }
299319
320+ auto pixel_size = get_pixel_size (texture->get_format ());
321+ size_t data_size = (size_t )effective_region.width () * effective_region.height () * pixel_size;
322+
323+ auto device = device_.lock ();
324+ auto allocation = device->allocate_staging (data_size);
325+
300326 Command cmd{};
301327 cmd.type = CommandType::ReadTexture;
302328
@@ -307,8 +333,18 @@ void CommandEncoder::read_texture(const std::shared_ptr<Texture> &texture, RectI
307333 args.width = effective_region.width ();
308334 args.height = effective_region.height ();
309335 args.data = dst;
336+ args.staging_buffer = allocation.buffer .get ();
337+ args.staging_offset = (uint32_t )allocation.offset ;
310338
311339 commands_.push_back (cmd);
340+
341+ add_callback ([allocation, dst, data_size, device] {
342+ void *mapped_ptr = device->map_staging (allocation);
343+ memcpy (dst, mapped_ptr, data_size);
344+ device->unmap_staging (allocation);
345+ });
346+
347+ track_temporary_resource (allocation.buffer );
312348}
313349
314350} // namespace Pathfinder
0 commit comments