#include #include #include #include #include #import id getMetalDevice(void); id getMetalEncoder(void); kinc_g5_vertex_buffer_t *currentVertexBuffer = NULL; static void vertex_buffer_unset(kinc_g5_vertex_buffer_t *buffer) { if (currentVertexBuffer == buffer) currentVertexBuffer = NULL; } void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int count, kinc_g5_vertex_structure_t *structure, bool gpuMemory, int instanceDataStepRate) { memset(&buffer->impl, 0, sizeof(buffer->impl)); buffer->impl.myCount = count; buffer->impl.gpuMemory = gpuMemory; for (int i = 0; i < structure->size; ++i) { kinc_g5_vertex_element_t element = structure->elements[i]; buffer->impl.myStride += kinc_g4_vertex_data_size(element.data); } id device = getMetalDevice(); MTLResourceOptions options = MTLResourceCPUCacheModeWriteCombined; #ifdef KINC_APPLE_SOC options |= MTLResourceStorageModeShared; #else if (gpuMemory) { options |= MTLResourceStorageModeManaged; } else { options |= MTLResourceStorageModeShared; } #endif id buf = [device newBufferWithLength:count * buffer->impl.myStride options:options]; buffer->impl.mtlBuffer = (__bridge_retained void *)buf; buffer->impl.lastStart = 0; buffer->impl.lastCount = 0; } void kinc_g5_vertex_buffer_destroy(kinc_g5_vertex_buffer_t *buf) { id buffer = (__bridge_transfer id)buf->impl.mtlBuffer; buffer = nil; buf->impl.mtlBuffer = NULL; vertex_buffer_unset(buf); } float *kinc_g5_vertex_buffer_lock_all(kinc_g5_vertex_buffer_t *buf) { buf->impl.lastStart = 0; buf->impl.lastCount = kinc_g5_vertex_buffer_count(buf); id buffer = (__bridge id)buf->impl.mtlBuffer; float *floats = (float *)[buffer contents]; return floats; } float *kinc_g5_vertex_buffer_lock(kinc_g5_vertex_buffer_t *buf, int start, int count) { buf->impl.lastStart = start; buf->impl.lastCount = count; id buffer = (__bridge id)buf->impl.mtlBuffer; float *floats = (float *)[buffer contents]; return &floats[start * buf->impl.myStride / sizeof(float)]; } void kinc_g5_vertex_buffer_unlock_all(kinc_g5_vertex_buffer_t *buf) { #ifndef KINC_APPLE_SOC if (buf->impl.gpuMemory) { id buffer = (__bridge id)buf->impl.mtlBuffer; NSRange range; range.location = buf->impl.lastStart * buf->impl.myStride; range.length = buf->impl.lastCount * buf->impl.myStride; [buffer didModifyRange:range]; } #endif } void kinc_g5_vertex_buffer_unlock(kinc_g5_vertex_buffer_t *buf, int count) { #ifndef KINC_APPLE_SOC if (buf->impl.gpuMemory) { id buffer = (__bridge id)buf->impl.mtlBuffer; NSRange range; range.location = buf->impl.lastStart * buf->impl.myStride; range.length = count * buf->impl.myStride; [buffer didModifyRange:range]; } #endif } int kinc_g5_internal_vertex_buffer_set(kinc_g5_vertex_buffer_t *buf, int offset_) { currentVertexBuffer = buf; id encoder = getMetalEncoder(); id buffer = (__bridge id)buf->impl.mtlBuffer; [encoder setVertexBuffer:buffer offset:offset_ * buf->impl.myStride atIndex:0]; return offset_; } int kinc_g5_vertex_buffer_count(kinc_g5_vertex_buffer_t *buffer) { return buffer->impl.myCount; } int kinc_g5_vertex_buffer_stride(kinc_g5_vertex_buffer_t *buffer) { return buffer->impl.myStride; }