У меня есть металлическое вычислительное ядро, которое принимает две текстуры для аргументов.Тем не менее, я столкнулся с проблемой, когда ядро не работает.Я сократил проблему до этого простого ядра.
#include <metal_stdlib>
using namespace metal;
kernel void test_texture( texture2d<float, access::sample> tex1 [[texture(0)]],
texture2d<float, access::sample> tex2 [[texture(1)]],
device float *buf [[buffer(0)]],
uint idx [[thread_position_in_grid]]) {
buf[idx] = 100;
}
И следующий код хоста.
#import <Metal/Metal.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
const size_t max_buffer = 128000000;
const size_t max_texture = 16384;
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
id<MTLLibrary> library = [device newDefaultLibrary];
id<MTLCommandQueue> queue = [device newCommandQueue];
id<MTLBuffer> buffer = [device newBufferWithLength:sizeof(float)*max_buffer
options:MTLResourceCPUCacheModeDefaultCache |
MTLResourceStorageModeManaged];
MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
textureDescriptor.textureType = MTLTextureType2D;
textureDescriptor.pixelFormat = MTLPixelFormatR32Float;
textureDescriptor.width = max_texture;
textureDescriptor.height = max_texture;
textureDescriptor.depth = 1;
textureDescriptor.mipmapLevelCount = 1;
textureDescriptor.sampleCount = 1;
textureDescriptor.arrayLength = 1;
textureDescriptor.resourceOptions = MTLResourceStorageModePrivate |
MTLResourceCPUCacheModeDefaultCache;
textureDescriptor.cpuCacheMode = MTLCPUCacheModeDefaultCache;
textureDescriptor.storageMode = MTLStorageModePrivate;
textureDescriptor.usage = MTLTextureUsageShaderRead;
id<MTLTexture> texture1 = [device newTextureWithDescriptor:textureDescriptor];
id<MTLTexture> texture2 = [device newTextureWithDescriptor:textureDescriptor];
MTLComputePipelineDescriptor *discriptor = [[MTLComputePipelineDescriptor alloc] init];
discriptor.computeFunction = [library newFunctionWithName:@"test_texture"];
discriptor.threadGroupSizeIsMultipleOfThreadExecutionWidth = YES;
id<MTLComputePipelineState> pipeline = [device newComputePipelineStateWithDescriptor:discriptor
options:MTLPipelineOptionNone
reflection:NULL
error:NULL];
id<MTLCommandBuffer> command_buffer = queue.commandBuffer;
id<MTLComputeCommandEncoder> compute_encoder = [command_buffer computeCommandEncoder];
[compute_encoder setComputePipelineState:pipeline];
[compute_encoder setTexture:texture1 atIndex:0];
[compute_encoder setTexture:texture2 atIndex:1];
[compute_encoder setBuffer:buffer offset:0 atIndex:0];
[compute_encoder dispatchThreads:MTLSizeMake(max_buffer, 1, 1) threadsPerThreadgroup:MTLSizeMake(1024, 1, 1)];
[compute_encoder endEncoding];
id<MTLBlitCommandEncoder> blit_encoder = [command_buffer blitCommandEncoder];
[blit_encoder synchronizeResource:buffer];
[blit_encoder endEncoding];
[command_buffer commit];
[command_buffer waitUntilCompleted];
float *result = (float *)buffer.contents;
NSLog(@"%f",result[0]);
}
return 0;
}
Если я закомментирую второй аргумент текстуры, я получу ожидаемое значениекогда я читаю буфер результатов.Однако, когда я оставляю второй аргумент текстуры нетронутым, создается впечатление, что ядро не работает, а значение в результате получается равным нулю.Есть ли ограничение на количество текстур, которые могут быть выбраны в вычислительном ядре на MacOS?Или проблема вызвана тем, что я использовал максимальные размеры текстур в обеих текстурах (у меня не хватает памяти текстур)? сильный текст