Метод, указанный в вопросе, работает хорошо. Но для завершения альтернативным способом чтения текстур с использованием ненормализованных (и / или нормализованных координат устройства) было бы использование семплеров.
Создайте сэмплер:
id<MTLSamplerState> GetSamplerState()
{
MTLSamplerDescriptor *desc = [[MTLSamplerDescriptor alloc] autorelease];
desc.minFilter = MTLSamplerMinMagFilterNearest;
desc.magFilter = MTLSamplerMinMagFilterNearest;
desc.mipFilter = MTLSamplerMipFilterNotMipmapped;
desc.maxAnisotropy = 1;
desc.sAddressMode = MTLSamplerAddressModeClampToEdge;
desc.tAddressMode = MTLSamplerAddressModeClampToEdge;
desc.rAddressMode = MTLSamplerAddressModeClampToEdge;
// The key point: specifies that the sampler reads non-normalized coordinates
desc.normalizedCoordinates = NO;
desc.lodMinClamp = 0.0f;
desc.lodMaxClamp = FLT_MAX;
id <MTLSamplerState> sampler_state = nil;
sampler_state = [[device_ newSamplerStateWithDescriptor:desc] autorelease];
// Release the descriptor
desc = nil;
return sampler_state;
}
А затем прикрепите его к кодировщику вычислительной команды:
id <MTLComputeCommandEncoder> compute_encoder = [comand_buffer computeCommandEncoder];
id<MTLSamplerState> ss = GetSamplerState();
// Attach the sampler state to the encoder, say at sampler bind point 0
[compute_encoder setSamplerState:ss atIndex:0];
// And set your texture, say at texture bind point 0
[compute_encoder setTexture:my_texture atIndex:0];
Наконец, используйте его в ядре:
// An example kernel that samples from a texture,
// writes one component of the sample into an output buffer
kernel void compute_main(
texture2d<uint, access::sample> tex_to_sample [[ texture(0) ]],
sampler smp [[ sampler(0) ]],
device uint *out [[buffer(0)]],
uint2 tid [[thread_position_in_grid]])
{
out[tid] = tex_to_sample.sample(smp, tid).x;
}
Использование сэмплера позволяет вам указать параметры для сэмплирования (например, фильтрацию). Вы также можете получить доступ к текстуре по-разному, используя разные семплеры, подключенные к одному и тому же ядру. Sampler также избегает необходимости проходить и проверять границы размеров текстуры.
Обратите внимание, что сэмплер также можно настроить из вычислительного ядра. См. Раздел 2.6 «Сэмплеры» в Спецификации языка затенения металлов
Наконец, одно из основных различий между функцией чтения (с использованием gid, как указано в вопросе) и выборкой с использованием сэмплера заключается в том, что read () принимает целочисленные координаты, тогда как sample () принимает координаты с плавающей запятой. Таким образом, целочисленные координаты, переданные в образец, будут преобразованы в эквивалентные числа с плавающей запятой.
person
codingminion
schedule
09.05.2017