Рендеринг 2 отдельных MtkView с вызовом 1 Draw - PullRequest
0 голосов
/ 24 октября 2018

Имея два разных (не перекрывающих друг друга) MtkViews работает правильно.У каждого разные Униформы, Вершины и разные Примитивные Типы.Уже сделано одно из обоих представлений комбинацией различных конвейеров рендеринга с одним RenderCommandEncoder.Работает отлично.Чтобы снизить энергетическое воздействие на устройства iOS, я уменьшил mtkview.preferredFramesPerSecond = 24; на каждом просмотре.

Есть ли способ обрабатывать их параллельно на GPU, чтобы они не суммировали рендеринг друг за другом?

Предполагается, что мне нужно использовать

id<MTLParallelRenderCommandEncoder> renderEncoder = 
[commandBuffer parallelRenderCommandEncoderWithDescriptor:renderPassDescriptor];

, но этоКодировщик не знает о ...

[renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];

... который я, конечно, использовал с обычным RenderCommandEncoder.

Так как правильно настроить MTLParallelRenderCommandEncoder

- (void)drawInMTKView:(nonnull MTKView *)view {
    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    //commandBuffer.label = @"CombiCommand";

    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    if(renderPassDescriptor != nil) {
        renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0,0,0,0);


        id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
        //renderEncoder.label = @"CombiRenderEncoder";
        [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];


        //----CHART----
        [renderEncoder setRenderPipelineState:_chartPipelineState];
        if (_pat->infoCC.needsDisplay ) {
            [CCChartMetalRenderer changeChartDataWithBuffer:_chartVertexBuffer];
            _chartUniform.statisch = somedata.isStatic;
            _pat->infoCC.needsDisplay=false;
        }
        [renderEncoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:IndexViewportSize];
        [renderEncoder setVertexBytes:&_chartUniform length:sizeof(_chartUniform) atIndex:IndexUniforms];
        [renderEncoder setVertexBuffer:_chartVertexBuffer offset:0 atIndex:IndexVertices];
        [renderEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:_chartVerticesCount];


        //----NOTE----
        [renderEncoder setRenderPipelineState:_notePipelineState];
        if (_pat->infoNotePatch.needsDisplay ) {
            [NoteMetalRenderer changeVertexDataWithMtlBuffer:_noteVertexBuffer];
            _noteUniform.color = simd_make_float4(1.0, 0.0, 1.0, 1.0);
            _noteUniform.isOn = somedata.isOn;
            _pat->infoNotePatch.needsDisplay=false;
        }
        [renderEncoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:IndexViewportSize];
        [renderEncoder setVertexBytes:&_noteUniform length:sizeof(_noteUniform) atIndex:IndexUniforms];
        [renderEncoder setVertexBuffer:_noteVertexBuffer offset:0 atIndex:IndexVertices];
        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:_notesCount * sizeof(NoteVertex)];


        //----POS----
        [renderEncoder setRenderPipelineState:_posPipelineState];
        _posUniform.statischValue = somedata.value;
        _posUniform.statisch = somedata.isStatic;
        [renderEncoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:IndexViewportSize];
        [renderEncoder setVertexBytes:&_posUniform length:sizeof(_posUniform) atIndex:IndexUniforms];
        [renderEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:16];

        //---ENDENCODIG---
        [renderEncoder endEncoding];
        [commandBuffer presentDrawable:view.currentDrawable];
    }
    [commandBuffer commit];
}

и второй mtkView

- (void)drawInMTKView:(nonnull MTKView *)view {
    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    //commandBuffer.label = @"CCTableCommand";

    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    if(renderPassDescriptor != nil) {
        renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0,0,0,0);

        id<MTLRenderCommandEncoder> renderEncoder =
        [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
        //renderEncoder.label = @"CCTableRenderEncoder";
        [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];

        [renderEncoder setRenderPipelineState:_pipelineState];
        [self.class changeVertexDataWithPatch:_pat Ch:_viewCH Quantize:_quantized mtlBuffer:_vertexBuffer];
        _tableUniform.isOn = somedata.isOn;
        [renderEncoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:IndexViewportSize];
        [renderEncoder setVertexBytes:&_tableUniform length:sizeof(_tableUniform) atIndex:IndexUniforms];
        [renderEncoder setVertexBuffer:_vertexBuffer offset:0 atIndex:IndexVertices];

        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:_numVertices];

        [renderEncoder endEncoding];
        [commandBuffer presentDrawable:view.currentDrawable];
    }
    [commandBuffer commit];
}

Ответы [ 2 ]

0 голосов
/ 03 сентября 2019

Умное использование ViewportSize для слоев Encoder и UIView позволяет выполнять рендеринг «один раз».

- (void)drawInMTKView:(nonnull MTKView *)view {
    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];

    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    if(renderPassDescriptor != nil) {

        // allows for transparent layering
        renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0,0,0,0);

        // allowes the encoders to work on different threads
        id<MTLParallelRenderCommandEncoder> parallelRenderEnc = [commandBuffer parallelRenderCommandEncoderWithDescriptor:renderPassDescriptor];

        // so we need to get the renderEncoders from the parallelRenderEncoder
        id<MTLRenderCommandEncoder> renderEncoder1 = [parallelRenderEnc renderCommandEncoder];
        id<MTLRenderCommandEncoder> renderEncoder2 = [parallelRenderEnc renderCommandEncoder];

        // each of which need their own viewport settings, they dont need to be equaly
        [renderEncoder1 setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];
        [renderEncoder2 setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];

        [renderEncoder1 setRenderPipelineState:_renderPipeLine1];
        //do your Metal SharedBuffer stuff for encoder1 here
        //renderEncoder1 set uniform buffer/bytes
        //renderEncoder1 set vertex buffer/bytes
        //renderEncoder1 drawPrimitives with the MTLPrimitiveType you want

        [renderEncoder2 setRenderPipelineState:_renderPipeLine2];
        //do your Metal SharedBuffer stuff for encoder2 here
        //renderEncoder2 set uniform buffer/bytes
        //renderEncoder2 set vertex buffer/bytes
        //renderEncoder2 drawPrimitives with the MTLPrimitiveType you want

        [renderEncoder1 endEncoding];
        [renderEncoder2 endEncoding];

       [parallelRenderEnc endEncoding]
       [commandBuffer presentDrawable:view.currentDrawable];
    }
    [commandBuffer commit];
}

Вы можете решить, какие из командEncoders разрешено запускать в том же потоке или самостоятельнонить.Теперь вы можете использовать tripleBuffering, чтобы заставить процессор и графический процессор работать не в одном буфере одновременно.

0 голосов
/ 24 октября 2018

Как вы пришли к выводу, что кодирование параллельных команд является решением?

Целью кодирования параллельных команд является распределение работы по кодированию на стороне ЦП между потоками.Это не имеет никакого отношения к тому, как эта работа в конечном счете запланирована и выполнена на GPU.Если вы привязаны к процессору, у вас может быть случай использования параллельного кодирования, но каждый кодировщик команд параллельного рендеринга может кодировать только те команды, которые влияют на одно представление.

Невозможно выполнить рендеринг до двух MTKView с.одновременно с одним вызовом отрисовки, потому что каждый вызов отрисовки кодируется с помощью кодировщика команды рендеринга, который связан с текущим отображаемым изображением соответствующего ему вида.

Похоже, вы заблуждаетесь, что кодируемая вами работа обязательно будет выполняться последовательнона ГПУ.Это не тот случай.Если можно запланировать одновременное выполнение независимой работы, драйвер GPU сделает это, но это не зависит от вас.

...