1 /*
2 * Copyright 2016 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/ganesh/vk/GrVkPipelineStateDataManager.h"
9
10 #include "include/gpu/ganesh/GrDirectContext.h"
11 #include "include/private/base/SkAssert.h"
12 #include "include/private/base/SkDebug.h"
13 #include "include/private/base/SkTArray.h"
14 #include "include/private/gpu/ganesh/GrTypesPriv.h"
15 #include "src/base/SkAutoMalloc.h"
16 #include "src/core/SkSLTypeShared.h"
17 #include "src/gpu/ganesh/GrDirectContextPriv.h"
18 #include "src/gpu/ganesh/GrGpuBuffer.h"
19 #include "src/gpu/ganesh/GrResourceProvider.h"
20 #include "src/gpu/ganesh/GrShaderVar.h"
21 #include "src/gpu/ganesh/vk/GrVkCaps.h"
22 #include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
23 #include "src/gpu/ganesh/vk/GrVkGpu.h"
24
25 #include <cstring>
26
GrVkPipelineStateDataManager(const UniformInfoArray & uniforms,uint32_t uniformSize,bool usePushConstants)27 GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArray& uniforms,
28 uint32_t uniformSize,
29 bool usePushConstants)
30 : INHERITED(uniforms.count(), uniformSize)
31 , fUsePushConstants(usePushConstants) {
32 // We must add uniforms in same order as the UniformInfoArray so that UniformHandles already
33 // owned by other objects will still match up here.
34 int i = 0;
35 GrVkUniformHandler::Layout memLayout = usePushConstants ? GrVkUniformHandler::kStd430Layout
36 : GrVkUniformHandler::kStd140Layout;
37 for (const auto& uniformInfo : uniforms.items()) {
38 Uniform& uniform = fUniforms[i];
39 SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() ||
40 uniformInfo.fVariable.getArrayCount() > 0);
41 SkDEBUGCODE(
42 uniform.fArrayCount = uniformInfo.fVariable.getArrayCount();
43 )
44
45 uniform.fOffset = uniformInfo.fOffsets[memLayout];
46 uniform.fType = uniformInfo.fVariable.getType();
47 ++i;
48 }
49 }
50
uploadUniforms(GrVkGpu * gpu,VkPipelineLayout layout,GrVkCommandBuffer * commandBuffer)51 std::pair<sk_sp<GrGpuBuffer>, bool> GrVkPipelineStateDataManager::uploadUniforms(
52 GrVkGpu* gpu, VkPipelineLayout layout, GrVkCommandBuffer* commandBuffer) {
53 if (fUniformSize == 0) {
54 return std::make_pair(nullptr, true);
55 }
56 if (fUsePushConstants) {
57 commandBuffer->pushConstants(gpu, layout, gpu->vkCaps().getPushConstantStageFlags(),
58 0, fUniformSize, fUniformData.get());
59 fUniformBuffer = nullptr;
60 } else {
61 if (fUniformsDirty) {
62 GrResourceProvider* resourceProvider = gpu->getContext()->priv().resourceProvider();
63 fUniformBuffer = resourceProvider->createBuffer(fUniformData.get(),
64 fUniformSize,
65 GrGpuBufferType::kUniform,
66 kDynamic_GrAccessPattern);
67 if (!fUniformBuffer) {
68 return std::make_pair(nullptr, false);
69 }
70 fUniformsDirty = false;
71 }
72 }
73
74 return std::make_pair(fUniformBuffer, true);
75 }
76
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const77 void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
78 int arrayCount,
79 const int32_t v[]) const {
80 if (fUsePushConstants) {
81 const Uniform& uni = fUniforms[u.toIndex()];
82 SkASSERT(uni.fType == SkSLType::kInt || uni.fType == SkSLType::kShort);
83 SkASSERT(arrayCount > 0);
84 SkASSERT(arrayCount <= uni.fArrayCount ||
85 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
86
87 void* buffer = this->getBufferPtrAndMarkDirty(uni);
88 SkASSERT(sizeof(int32_t) == 4);
89 memcpy(buffer, v, arrayCount * sizeof(int32_t));
90 } else {
91 return this->INHERITED::set1iv(u, arrayCount, v);
92 }
93 }
94
set1fv(UniformHandle u,int arrayCount,const float v[]) const95 void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
96 int arrayCount,
97 const float v[]) const {
98 if (fUsePushConstants) {
99 const Uniform& uni = fUniforms[u.toIndex()];
100 SkASSERT(uni.fType == SkSLType::kFloat || uni.fType == SkSLType::kHalf);
101 SkASSERT(arrayCount > 0);
102 SkASSERT(arrayCount <= uni.fArrayCount ||
103 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
104
105 void* buffer = this->getBufferPtrAndMarkDirty(uni);
106 SkASSERT(sizeof(float) == 4);
107 memcpy(buffer, v, arrayCount * sizeof(float));
108 } else {
109 return this->INHERITED::set1fv(u, arrayCount, v);
110 }
111 }
112
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const113 void GrVkPipelineStateDataManager::set2iv(UniformHandle u,
114 int arrayCount,
115 const int32_t v[]) const {
116 if (fUsePushConstants) {
117 const Uniform& uni = fUniforms[u.toIndex()];
118 SkASSERT(uni.fType == SkSLType::kInt2 || uni.fType == SkSLType::kShort2);
119 SkASSERT(arrayCount > 0);
120 SkASSERT(arrayCount <= uni.fArrayCount ||
121 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
122
123 void* buffer = this->getBufferPtrAndMarkDirty(uni);
124 SkASSERT(sizeof(int32_t) == 4);
125 memcpy(buffer, v, arrayCount * 2 * sizeof(int32_t));
126 } else {
127 return this->INHERITED::set2iv(u, arrayCount, v);
128 }
129 }
130
set2fv(UniformHandle u,int arrayCount,const float v[]) const131 void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
132 int arrayCount,
133 const float v[]) const {
134 if (fUsePushConstants) {
135 const Uniform& uni = fUniforms[u.toIndex()];
136 SkASSERT(uni.fType == SkSLType::kFloat2 || uni.fType == SkSLType::kHalf2);
137 SkASSERT(arrayCount > 0);
138 SkASSERT(arrayCount <= uni.fArrayCount ||
139 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
140
141 void* buffer = this->getBufferPtrAndMarkDirty(uni);
142 SkASSERT(sizeof(float) == 4);
143 memcpy(buffer, v, arrayCount * 2 * sizeof(float));
144 } else {
145 return this->INHERITED::set2fv(u, arrayCount, v);
146 }
147 }
148
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const149 void GrVkPipelineStateDataManager::setMatrix2fv(UniformHandle u,
150 int arrayCount,
151 const float m[]) const {
152 if (fUsePushConstants) {
153 // upload as std430
154 const Uniform& uni = fUniforms[u.toIndex()];
155 SkASSERT(uni.fType == SkSLType::kFloat2x2 || uni.fType == SkSLType::kHalf2x2);
156 SkASSERT(arrayCount > 0);
157 SkASSERT(arrayCount <= uni.fArrayCount ||
158 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
159
160 void* buffer = fUniformData.get();
161 fUniformsDirty = true;
162
163 static_assert(sizeof(float) == 4);
164 buffer = static_cast<char*>(buffer) + uni.fOffset;
165 memcpy(buffer, m, arrayCount * 2 * 2 * sizeof(float));
166 } else {
167 this->INHERITED::setMatrix2fv(u, arrayCount, m);
168 }
169 }
170
releaseData()171 void GrVkPipelineStateDataManager::releaseData() { fUniformBuffer.reset(); }
172