1/* 2 * Copyright 2018 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 8#include "src/gpu/mtl/GrMtlPipelineStateDataManager.h" 9 10#include "src/gpu/mtl/GrMtlBuffer.h" 11#include "src/gpu/mtl/GrMtlGpu.h" 12#include "src/gpu/mtl/GrMtlRenderCommandEncoder.h" 13 14#if !__has_feature(objc_arc) 15#error This file must be compiled with Arc. Use -fobjc-arc flag 16#endif 17 18GR_NORETAIN_BEGIN 19 20GrMtlPipelineStateDataManager::GrMtlPipelineStateDataManager(const UniformInfoArray& uniforms, 21 uint32_t uniformSize) 22 : INHERITED(uniforms.count(), uniformSize) { 23 // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already 24 // owned by other objects will still match up here. 25 int i = 0; 26 for (const auto& uniformInfo : uniforms.items()) { 27 Uniform& uniform = fUniforms[i]; 28 SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() || 29 uniformInfo.fVariable.getArrayCount() > 0); 30 SkDEBUGCODE( 31 uniform.fArrayCount = uniformInfo.fVariable.getArrayCount(); 32 ) 33 uniform.fOffset = uniformInfo.fUBOffset; 34 uniform.fType = uniformInfo.fVariable.getType(); 35 ++i; 36 } 37 38 fWrite16BitUniforms = true; 39} 40 41void GrMtlPipelineStateDataManager::set1iv(UniformHandle u, 42 int arrayCount, 43 const int32_t v[]) const { 44 const Uniform& uni = fUniforms[u.toIndex()]; 45 SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); 46 SkASSERT(arrayCount > 0); 47 SkASSERT(arrayCount <= uni.fArrayCount || 48 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 49 50 void* buffer = this->getBufferPtrAndMarkDirty(uni); 51 this->copyUniforms(buffer, v, arrayCount, uni.fType); 52} 53 54void GrMtlPipelineStateDataManager::set1fv(UniformHandle u, 55 int arrayCount, 56 const float v[]) const { 57 const Uniform& uni = fUniforms[u.toIndex()]; 58 SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); 59 SkASSERT(arrayCount > 0); 60 SkASSERT(arrayCount <= uni.fArrayCount || 61 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 62 63 void* buffer = this->getBufferPtrAndMarkDirty(uni); 64 this->copyUniforms(buffer, v, arrayCount, uni.fType); 65} 66 67void GrMtlPipelineStateDataManager::set2iv(UniformHandle u, 68 int arrayCount, 69 const int32_t v[]) const { 70 const Uniform& uni = fUniforms[u.toIndex()]; 71 SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); 72 SkASSERT(arrayCount > 0); 73 SkASSERT(arrayCount <= uni.fArrayCount || 74 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 75 76 void* buffer = this->getBufferPtrAndMarkDirty(uni); 77 this->copyUniforms(buffer, v, arrayCount * 2, uni.fType); 78} 79 80void GrMtlPipelineStateDataManager::set2fv(UniformHandle u, 81 int arrayCount, 82 const float v[]) const { 83 const Uniform& uni = fUniforms[u.toIndex()]; 84 SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); 85 SkASSERT(arrayCount > 0); 86 SkASSERT(arrayCount <= uni.fArrayCount || 87 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 88 89 void* buffer = this->getBufferPtrAndMarkDirty(uni); 90 this->copyUniforms(buffer, v, arrayCount * 2, uni.fType); 91} 92 93void GrMtlPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const { 94 this->setMatrix2fv(u, 1, matrix); 95} 96 97void GrMtlPipelineStateDataManager::setMatrix2fv(UniformHandle u, 98 int arrayCount, 99 const float m[]) const { 100 const Uniform& uni = fUniforms[u.toIndex()]; 101 SkASSERT(uni.fType == kFloat2x2_GrSLType || uni.fType == kHalf2x2_GrSLType); 102 SkASSERT(arrayCount > 0); 103 SkASSERT(arrayCount <= uni.fArrayCount || 104 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 105 106 void* buffer = this->getBufferPtrAndMarkDirty(uni); 107 this->copyUniforms(buffer, m, arrayCount * 4, uni.fType); 108} 109 110void GrMtlPipelineStateDataManager::uploadAndBindUniformBuffers( 111 GrMtlGpu* gpu, 112 GrMtlRenderCommandEncoder* renderCmdEncoder) const { 113 if (fUniformSize && fUniformsDirty) { 114 fUniformsDirty = false; 115 if (@available(macOS 10.11, iOS 8.3, *)) { 116 if (fUniformSize <= gpu->caps()->maxPushConstantsSize()) { 117 renderCmdEncoder->setVertexBytes(fUniformData.get(), fUniformSize, 118 GrMtlUniformHandler::kUniformBinding); 119 renderCmdEncoder->setFragmentBytes(fUniformData.get(), fUniformSize, 120 GrMtlUniformHandler::kUniformBinding); 121 return; 122 } 123 } 124 125 // upload the data 126 GrRingBuffer::Slice slice = gpu->uniformsRingBuffer()->suballocate(fUniformSize); 127 GrMtlBuffer* buffer = (GrMtlBuffer*) slice.fBuffer; 128 char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset; 129 memcpy(destPtr, fUniformData.get(), fUniformSize); 130 131 renderCmdEncoder->setVertexBuffer(buffer->mtlBuffer(), slice.fOffset, 132 GrMtlUniformHandler::kUniformBinding); 133 renderCmdEncoder->setFragmentBuffer(buffer->mtlBuffer(), slice.fOffset, 134 GrMtlUniformHandler::kUniformBinding); 135 } 136} 137 138void GrMtlPipelineStateDataManager::resetDirtyBits() { 139 fUniformsDirty = true; 140} 141 142GR_NORETAIN_END 143