• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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