GrMtlCommandBuffer.mm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright 2019 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/gpu/mtl/GrMtlCommandBuffer.h"
  8. #include "src/gpu/mtl/GrMtlGpu.h"
  9. #include "src/gpu/mtl/GrMtlGpuCommandBuffer.h"
  10. #include "src/gpu/mtl/GrMtlPipelineState.h"
  11. #if !__has_feature(objc_arc)
  12. #error This file must be compiled with Arc. Use -fobjc-arc flag
  13. #endif
  14. GrMtlCommandBuffer* GrMtlCommandBuffer::Create(id<MTLCommandQueue> queue) {
  15. id<MTLCommandBuffer> mtlCommandBuffer;
  16. mtlCommandBuffer = [queue commandBuffer];
  17. if (nil == mtlCommandBuffer) {
  18. return nullptr;
  19. }
  20. mtlCommandBuffer.label = @"GrMtlCommandBuffer::Create";
  21. return new GrMtlCommandBuffer(mtlCommandBuffer);
  22. }
  23. GrMtlCommandBuffer::~GrMtlCommandBuffer() {
  24. this->endAllEncoding();
  25. fCmdBuffer = nil;
  26. }
  27. id<MTLBlitCommandEncoder> GrMtlCommandBuffer::getBlitCommandEncoder() {
  28. if (nil != fActiveRenderCommandEncoder) {
  29. [fActiveRenderCommandEncoder endEncoding];
  30. fActiveRenderCommandEncoder = nil;
  31. }
  32. if (nil == fActiveBlitCommandEncoder) {
  33. fActiveBlitCommandEncoder = [fCmdBuffer blitCommandEncoder];
  34. }
  35. fPreviousRenderPassDescriptor = nil;
  36. return fActiveBlitCommandEncoder;
  37. }
  38. static bool compatible(const MTLRenderPassAttachmentDescriptor* first,
  39. const MTLRenderPassAttachmentDescriptor* second,
  40. const GrMtlPipelineState* pipelineState) {
  41. // Check to see if the previous descriptor is compatible with the new one.
  42. // They are compatible if:
  43. // * they share the same rendertargets
  44. // * the first's store actions are either Store or DontCare
  45. // * the second's load actions are either Load or DontCare
  46. // * the second doesn't sample from any rendertargets in the first
  47. bool renderTargetsMatch = (first.texture == second.texture);
  48. bool storeActionsValid = first.storeAction == MTLStoreActionStore ||
  49. first.storeAction == MTLStoreActionDontCare;
  50. bool loadActionsValid = second.loadAction == MTLLoadActionLoad ||
  51. second.loadAction == MTLLoadActionDontCare;
  52. bool secondDoesntSampleFirst = (!pipelineState ||
  53. pipelineState->doesntSampleAttachment(first)) &&
  54. second.storeAction != MTLStoreActionMultisampleResolve;
  55. return renderTargetsMatch &&
  56. (nil == first.texture ||
  57. (storeActionsValid && loadActionsValid && secondDoesntSampleFirst));
  58. }
  59. id<MTLRenderCommandEncoder> GrMtlCommandBuffer::getRenderCommandEncoder(
  60. MTLRenderPassDescriptor* descriptor, const GrMtlPipelineState* pipelineState,
  61. GrMtlGpuRTCommandBuffer* gpuCommandBuffer) {
  62. if (nil != fPreviousRenderPassDescriptor) {
  63. if (compatible(fPreviousRenderPassDescriptor.colorAttachments[0],
  64. descriptor.colorAttachments[0], pipelineState) &&
  65. compatible(fPreviousRenderPassDescriptor.stencilAttachment,
  66. descriptor.stencilAttachment, pipelineState)) {
  67. return fActiveRenderCommandEncoder;
  68. }
  69. }
  70. this->endAllEncoding();
  71. fActiveRenderCommandEncoder = [fCmdBuffer renderCommandEncoderWithDescriptor:descriptor];
  72. if (gpuCommandBuffer) {
  73. gpuCommandBuffer->initRenderState(fActiveRenderCommandEncoder);
  74. }
  75. fPreviousRenderPassDescriptor = descriptor;
  76. return fActiveRenderCommandEncoder;
  77. }
  78. void GrMtlCommandBuffer::commit(bool waitUntilCompleted) {
  79. this->endAllEncoding();
  80. [fCmdBuffer commit];
  81. if (waitUntilCompleted) {
  82. [fCmdBuffer waitUntilCompleted];
  83. }
  84. if (MTLCommandBufferStatusError == fCmdBuffer.status) {
  85. NSString* description = fCmdBuffer.error.localizedDescription;
  86. const char* errorString = [description UTF8String];
  87. SkDebugf("Error submitting command buffer: %s\n", errorString);
  88. }
  89. fCmdBuffer = nil;
  90. }
  91. void GrMtlCommandBuffer::endAllEncoding() {
  92. if (nil != fActiveRenderCommandEncoder) {
  93. [fActiveRenderCommandEncoder endEncoding];
  94. fActiveRenderCommandEncoder = nil;
  95. }
  96. if (nil != fActiveBlitCommandEncoder) {
  97. [fActiveBlitCommandEncoder endEncoding];
  98. fActiveBlitCommandEncoder = nil;
  99. }
  100. }