diff --git a/base/sources/backends/metal_gpu.m b/base/sources/backends/metal_gpu.m index 897ff647..75d25aa9 100644 --- a/base/sources/backends/metal_gpu.m +++ b/base/sources/backends/metal_gpu.m @@ -7,8 +7,6 @@ #import #import -#define GPU_FRAMEBUFFER_COUNT 1 - id getMetalLayer(void); id getMetalDevice(void); id getMetalQueue(void); @@ -28,6 +26,10 @@ static MTLViewport current_viewport; static MTLScissorRect current_scissor; static MTLRenderPassDescriptor *render_pass_desc; static bool resized = false; +static gpu_texture_t *current_textures[16] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; static MTLBlendFactor convert_blending_factor(gpu_blending_factor_t factor) { switch (factor) { @@ -169,7 +171,7 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) { NSArray *arguments = [NSArray arrayWithObjects:constantsDesc, samplerDesc, textureDesc[0], textureDesc[1], textureDesc[2], textureDesc[3], textureDesc[4], textureDesc[5], textureDesc[6], textureDesc[7], textureDesc[8], textureDesc[9], textureDesc[10], textureDesc[11], textureDesc[12], textureDesc[13], textureDesc[14], textureDesc[15], nil]; argument_encoder = [device newArgumentEncoderWithArguments:arguments]; argument_buffer_step = [argument_encoder encodedLength]; - argument_buffer = [device newBufferWithLength:(argument_buffer_step * 2048) options:MTLResourceStorageModeShared]; + argument_buffer = [device newBufferWithLength:(argument_buffer_step * GPU_CONSTANT_BUFFER_MULTIPLE) options:MTLResourceStorageModeShared]; gpu_create_framebuffers(depth_buffer_bits); next_drawable(); @@ -227,6 +229,10 @@ void gpu_wait() { } void gpu_execute_and_wait() { + if (gpu_in_use) { + [command_encoder endEncoding]; + } + [command_buffer commit]; gpu_wait(); id queue = getMetalQueue(); @@ -321,6 +327,9 @@ void gpu_set_pipeline(gpu_pipeline_t *pipeline) { [command_encoder setDepthStencilState:depth_state]; [command_encoder setFrontFacingWinding:MTLWindingClockwise]; [command_encoder setCullMode:convert_cull_mode(pipeline->cull_mode)]; + for (int i = 0; i < 16; ++i) { + current_textures[i] = NULL; + } } void gpu_set_vertex_buffer(gpu_buffer_t *buffer) { @@ -378,21 +387,24 @@ void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data) { void gpu_set_constant_buffer(gpu_buffer_t *buffer, int offset, size_t size) { id buf = (__bridge id)buffer->impl.metal_buffer; - int i = constant_buffer_index; - [argument_encoder setArgumentBuffer:argument_buffer offset:argument_buffer_step * i]; + [argument_encoder setArgumentBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index]; [argument_encoder setBuffer:buf offset:offset atIndex:0]; [argument_encoder setSamplerState:linear_sampler atIndex:1]; - [command_encoder setVertexBuffer:argument_buffer offset:argument_buffer_step * i atIndex:1]; - [command_encoder setFragmentBuffer:argument_buffer offset:argument_buffer_step * i atIndex:1]; - [command_encoder useResource:buf usage:MTLResourceUsageRead stages:MTLRenderStageVertex|MTLRenderStageFragment]; + [command_encoder setVertexBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index atIndex:1]; + [command_encoder setFragmentBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index atIndex:1]; + [command_encoder useResource:buf usage:MTLResourceUsageRead stages:MTLRenderStageVertex|MTLRenderStageFragment]; + for (int i = 0; i < 16; ++i) { + if (current_textures[i] == NULL) { + break; + } + id tex = (__bridge id)current_textures[i]->impl._tex; + [argument_encoder setTexture:tex atIndex:i + 2]; + [command_encoder useResource:tex usage:MTLResourceUsageRead stages:MTLRenderStageVertex|MTLRenderStageFragment]; + } } void gpu_set_texture(int unit, gpu_texture_t *texture) { - id tex = (__bridge id)texture->impl._tex; - int i = constant_buffer_index; - [argument_encoder setArgumentBuffer:argument_buffer offset:argument_buffer_step * i]; - [argument_encoder setTexture:tex atIndex:unit + 2]; - [command_encoder useResource:tex usage:MTLResourceUsageRead stages:MTLRenderStageVertex|MTLRenderStageFragment]; + current_textures[unit] = texture; } void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) { diff --git a/base/sources/iron_gpu.c b/base/sources/iron_gpu.c index 9d0022df..50629ea4 100644 --- a/base/sources/iron_gpu.c +++ b/base/sources/iron_gpu.c @@ -1,9 +1,6 @@ #include "iron_gpu.h" #include -#define CONSTANT_BUFFER_SIZE 256 -#define CONSTANT_BUFFER_MULTIPLE 2048 - static gpu_buffer_t constant_buffer; static bool gpu_thrown = false; @@ -20,8 +17,8 @@ int framebuffer_index = 0; void gpu_init(int depth_buffer_bits, bool vsync) { gpu_init_internal(depth_buffer_bits, vsync); - gpu_constant_buffer_init(&constant_buffer, CONSTANT_BUFFER_SIZE * CONSTANT_BUFFER_MULTIPLE); - gpu_constant_buffer_lock(&constant_buffer, 0, CONSTANT_BUFFER_SIZE); + gpu_constant_buffer_init(&constant_buffer, GPU_CONSTANT_BUFFER_SIZE * GPU_CONSTANT_BUFFER_MULTIPLE); + gpu_constant_buffer_lock(&constant_buffer, 0, GPU_CONSTANT_BUFFER_SIZE); } void gpu_begin(gpu_texture_t **targets, int count, gpu_texture_t *depth_buffer, unsigned flags, unsigned color, float depth) { @@ -64,21 +61,21 @@ void gpu_begin(gpu_texture_t **targets, int count, gpu_texture_t *depth_buffer, void gpu_draw() { gpu_constant_buffer_unlock(&constant_buffer); - gpu_set_constant_buffer(&constant_buffer, constant_buffer_index * CONSTANT_BUFFER_SIZE, CONSTANT_BUFFER_SIZE); + gpu_set_constant_buffer(&constant_buffer, constant_buffer_index * GPU_CONSTANT_BUFFER_SIZE, GPU_CONSTANT_BUFFER_SIZE); gpu_draw_internal(); constant_buffer_index++; - if (constant_buffer_index >= CONSTANT_BUFFER_MULTIPLE) { + if (constant_buffer_index >= GPU_CONSTANT_BUFFER_MULTIPLE) { constant_buffer_index = 0; } draw_calls++; - if (draw_calls + draw_calls_last >= CONSTANT_BUFFER_MULTIPLE) { + if (draw_calls + draw_calls_last >= GPU_CONSTANT_BUFFER_MULTIPLE) { draw_calls = draw_calls_last = constant_buffer_index = 0; gpu_execute_and_wait(); } - gpu_constant_buffer_lock(&constant_buffer, constant_buffer_index * CONSTANT_BUFFER_SIZE, CONSTANT_BUFFER_SIZE); + gpu_constant_buffer_lock(&constant_buffer, constant_buffer_index * GPU_CONSTANT_BUFFER_SIZE, GPU_CONSTANT_BUFFER_SIZE); } void gpu_end() { diff --git a/base/sources/iron_gpu.h b/base/sources/iron_gpu.h index 04f3c916..8225d51b 100644 --- a/base/sources/iron_gpu.h +++ b/base/sources/iron_gpu.h @@ -14,6 +14,8 @@ #define GPU_CLEAR_DEPTH 2 #define GPU_MAX_VERTEX_ELEMENTS 16 #define GPU_FRAMEBUFFER_COUNT 2 +#define GPU_CONSTANT_BUFFER_SIZE 256 +#define GPU_CONSTANT_BUFFER_MULTIPLE 2048 typedef enum gpu_texture_state { GPU_TEXTURE_STATE_SHADER_RESOURCE,