#include <msp/core/algorithm.h>
#include <msp/core/maputils.h>
#include <msp/graphics/vulkancontext_platform.h>
+#include <msp/stringcodec/utf8.h>
+#include <msp/strings/format.h>
#include "device.h"
#include "error.h"
#include "memoryallocator.h"
}
}
+string MemoryAllocator::get_debug() const
+{
+ static const StringCodec::unichar bar_chars[] = { 0xB7, 0x2596, 0x258C, 0x2597, 0x2584, 0x2599, 0x2590, 0x259F, 0x2588 }; // ·▖▌▗▄▙▐▟█
+
+ string debug;
+ for(unsigned i=0; i<pools.size(); ++i)
+ {
+ const Pool &pool = pools[i];
+
+ string pool_debug;
+ size_t total_heap = 0;
+ size_t total_used = 0;
+ for(unsigned j=0; j<regions.size(); ++j)
+ if(regions[j].pool==static_cast<int>(i))
+ {
+ total_heap += regions[j].size;
+ pool_debug += format(" Region %d: %d kB", j, (regions[j].size+512)/1024);
+ if(regions[j].direct)
+ pool_debug += ", direct";
+ pool_debug += '\n';
+
+ int block_index = -1;
+ for(unsigned k=0; (block_index<0 && k<blocks.size()); ++k)
+ if(blocks[k].region==static_cast<int>(j) && blocks[k].offset==0)
+ block_index = k;
+
+ unsigned slice_index = 0;
+ unsigned slice_data = 0;
+
+ string bar = " [";
+ string region_debug;
+ StringCodec::Utf8::Encoder bar_enc;
+ while(block_index>=0)
+ {
+ const Block &block = blocks[block_index];
+ if(block.allocated)
+ total_used += block.size;
+ const char *state_str = (block.allocated ? "allocated" : "free");
+ region_debug += format(" Block %d: %d bytes at %d, %s\n", block_index, block.size, block.offset, state_str);
+ block_index = block.next;
+
+ size_t block_end = block.offset+block.size;
+ while(1)
+ {
+ size_t slice_end = regions[j].size*(slice_index+1)/140;
+ slice_data |= 1<<(block.allocated+slice_index%2*2);
+ if(slice_end>block_end)
+ break;
+ ++slice_index;
+ if(slice_index%2==0)
+ {
+ slice_data = 5+((slice_data>>1)&5)-(slice_data&5);
+ bar_enc.encode_char(bar_chars[(slice_data&3)+3*((slice_data>>2)&3)], bar);
+ slice_data = 0;
+ }
+ }
+ }
+
+ bar += "]\n";
+ if(!regions[j].direct)
+ pool_debug += bar;
+ pool_debug += region_debug;
+ }
+
+ if(!pool_debug.empty())
+ {
+ MemoryType t = pool.type;
+ const char *type_str = (t==DEVICE_MEMORY ? "device" : t==STAGING_MEMORY ? "staging" :
+ t==STREAMING_MEMORY ? "streaming" : "unknown");
+ debug += format("Pool %d: %s, %d/%d kB used\n", i, type_str, (total_used+512)/1024, (total_heap+512)/1024);
+ debug += pool_debug;
+ }
+
+ if(!pool.free_blocks.empty())
+ {
+ debug += " Free blocks:\n";
+ for(unsigned j: pool.free_blocks)
+ {
+ const char *type = (blocks[j].type==BUFFER ? "buffer" : blocks[j].type==IMAGE ? "image" : "undecided");
+ debug += format(" Block %d: %d bytes, %s\n", j, blocks[j].size, type);
+ }
+ }
+ }
+
+ return debug;
+}
+
} // namespace GL
} // namespace Msp