1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "pipeline_state_object_gles.h"
17
18 #include <base/util/formats.h>
19 #include <render/device/pipeline_layout_desc.h>
20 #include <render/device/pipeline_state_desc.h>
21 #include <render/namespace.h>
22
23 #include "gles/device_gles.h"
24 #include "gles/gl_functions.h"
25 #include "gles/gpu_program_gles.h"
26 #include "util/log.h"
27
28 using namespace BASE_NS;
29
30 RENDER_BEGIN_NAMESPACE()
31 namespace {
FormatToVertexType(const VertexInputDeclaration::VertexInputAttributeDescription & attributeRef,GLuint & count,GLenum & type,GLboolean & normalized,bool & isFloat)32 void FormatToVertexType(const VertexInputDeclaration::VertexInputAttributeDescription& attributeRef, GLuint& count,
33 GLenum& type, GLboolean& normalized, bool& isFloat)
34 {
35 if (attributeRef.format == BASE_FORMAT_R16G16_SFLOAT) {
36 count = 2;
37 type = GL_HALF_FLOAT;
38 normalized = false;
39 isFloat = true;
40 } else if (attributeRef.format == BASE_FORMAT_R16G16B16_SFLOAT) {
41 count = 3;
42 type = GL_HALF_FLOAT;
43 normalized = false;
44 isFloat = true;
45 } else if (attributeRef.format == BASE_FORMAT_R16G16B16A16_SNORM) {
46 count = 4;
47 type = GL_SHORT;
48 normalized = true;
49 isFloat = true;
50 } else if (attributeRef.format == BASE_FORMAT_R16G16B16A16_SFLOAT) {
51 count = 4;
52 type = GL_HALF_FLOAT;
53 normalized = false;
54 isFloat = true;
55 } else if (attributeRef.format == BASE_FORMAT_R32G32B32_SFLOAT) {
56 count = 3;
57 type = GL_FLOAT;
58 normalized = false;
59 isFloat = true;
60 } else if (attributeRef.format == BASE_FORMAT_R32G32B32A32_SFLOAT) {
61 count = 4;
62 type = GL_FLOAT;
63 normalized = false;
64 isFloat = true;
65 } else if (attributeRef.format == BASE_FORMAT_R32G32_SFLOAT) {
66 count = 2;
67 type = GL_FLOAT;
68 normalized = false;
69 isFloat = true;
70 } else if (attributeRef.format == BASE_FORMAT_R32_SFLOAT) {
71 count = 1;
72 type = GL_FLOAT;
73 normalized = false;
74 isFloat = true;
75 } else if (attributeRef.format == BASE_FORMAT_R8G8B8A8_UINT) {
76 count = 4;
77 type = GL_UNSIGNED_BYTE;
78 normalized = false;
79 isFloat = false;
80 } else if (attributeRef.format == BASE_FORMAT_R8G8B8A8_UNORM) {
81 count = 4;
82 type = GL_UNSIGNED_BYTE;
83 normalized = true;
84 isFloat = true;
85 } else if (attributeRef.format == BASE_FORMAT_R32G32B32A32_UINT) {
86 count = 4;
87 type = GL_UNSIGNED_INT;
88 normalized = false;
89 isFloat = false;
90 } else if (attributeRef.format == BASE_FORMAT_R32_UINT) {
91 count = 1;
92 type = GL_UNSIGNED_INT;
93 normalized = false;
94 isFloat = false;
95 } else {
96 PLUGIN_ASSERT_MSG(false, "Unhandled attribute format");
97 }
98 }
99 } // namespace
100
GraphicsPipelineStateObjectGLES(Device & device,const GpuShaderProgram & gpuShaderProgram,const GraphicsState & graphicsState,const PipelineLayout & pipelineLayout,const VertexInputDeclarationView & vertexInputDeclaration,const ShaderSpecializationConstantDataView & specializationConstants,const DynamicStateFlags dynamicStateFlags,const RenderPassDesc & renderPassDesc,const array_view<const RenderPassSubpassDesc> & renderPassSubpassDescs,const uint32_t subpassIndex)101 GraphicsPipelineStateObjectGLES::GraphicsPipelineStateObjectGLES(Device& device,
102 const GpuShaderProgram& gpuShaderProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
103 const VertexInputDeclarationView& vertexInputDeclaration,
104 const ShaderSpecializationConstantDataView& specializationConstants, const DynamicStateFlags dynamicStateFlags,
105 const RenderPassDesc& renderPassDesc, const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs,
106 const uint32_t subpassIndex)
107 : GraphicsPipelineStateObject(), device_((DeviceGLES&)device)
108 {
109 plat_.graphicsState = graphicsState;
110 plat_.pipelineLayout = pipelineLayout;
111 for (const auto& t : vertexInputDeclaration.attributeDescriptions) {
112 plat_.vertexInputDeclaration.attributeDescriptions[plat_.vertexInputDeclaration.attributeDescriptionCount] = t;
113 plat_.vertexInputDeclaration.attributeDescriptionCount++;
114 }
115 for (const auto& t : vertexInputDeclaration.bindingDescriptions) {
116 plat_.vertexInputDeclaration.bindingDescriptions[plat_.vertexInputDeclaration.bindingDescriptionCount] = t;
117 plat_.vertexInputDeclaration.bindingDescriptionCount++;
118 }
119 plat_.renderPassDesc = renderPassDesc;
120 plat_.dynamicStateFlags = dynamicStateFlags;
121
122 const auto* source = (const GpuShaderProgramGLES*)&gpuShaderProgram;
123 specialized_.reset(source->Specialize(specializationConstants));
124 plat_.graphicsShader = specialized_.get();
125 MakeVAO();
126 }
127
GetOESProgram(const vector<OES_Bind> & oes_binds) const128 GpuShaderProgramGLES* GraphicsPipelineStateObjectGLES::GetOESProgram(const vector<OES_Bind>& oes_binds) const
129 {
130 BASE_NS::string key;
131 char tmp[16];
132 for (auto& bind : oes_binds) {
133 if (sprintf_s(tmp, sizeof(tmp), "%hhu_%hhu_", bind.set, bind.bind) < 0) {
134 PLUGIN_LOG_E("GetOESProgram: sprintf_s failed");
135 }
136 key += tmp;
137 }
138 if (auto it = oesPrograms_.find(key); it != oesPrograms_.end()) {
139 // return existing.
140 return it->second.get();
141 }
142 // create new one.
143 unique_ptr<GpuShaderProgramGLES> prog(specialized_->OesPatch(array_view<const OES_Bind> { oes_binds }));
144 return oesPrograms_.insert({ key, move(prog) }).first->second.get();
145 }
146
MakeVAO()147 void GraphicsPipelineStateObjectGLES::MakeVAO() noexcept
148 {
149 PLUGIN_ASSERT(device_.IsActive());
150 if (plat_.vao == 0) {
151 const auto& shaderdata = (const GpuShaderProgramPlatformDataGL&)plat_.graphicsShader->GetPlatformData();
152 PLUGIN_ASSERT(shaderdata.program != 0);
153 const uint32_t curVAO = device_.BoundVertexArray();
154 plat_.vao = device_.CreateVertexArray();
155 device_.BindVertexArray(plat_.vao);
156 const VertexInputDeclarationData& vertexInputDecl = plat_.vertexInputDeclaration;
157 for (size_t idx = 0; idx < vertexInputDecl.attributeDescriptionCount; ++idx) {
158 if (shaderdata.inputs[idx] != Gles::INVALID_LOCATION) {
159 const auto& attributeRef = vertexInputDecl.attributeDescriptions[idx];
160 GLuint count = 2;
161 GLenum type = GL_FLOAT;
162 GLboolean normalized = false;
163 bool isFloat = false;
164 FormatToVertexType(attributeRef, count, type, normalized, isFloat);
165 glEnableVertexAttribArray((GLuint)idx);
166 glVertexAttribBinding((GLuint)idx, attributeRef.binding);
167 if (isFloat) {
168 glVertexAttribFormat((GLuint)idx, (GLint)count, type, normalized, (GLuint)attributeRef.offset);
169 } else {
170 glVertexAttribIFormat((GLuint)idx, (GLint)count, type, (GLuint)attributeRef.offset);
171 }
172 } else {
173 glDisableVertexAttribArray((GLuint)idx);
174 }
175 }
176 device_.BindVertexArray(curVAO);
177 }
178 }
179
~GraphicsPipelineStateObjectGLES()180 GraphicsPipelineStateObjectGLES::~GraphicsPipelineStateObjectGLES()
181 {
182 if (plat_.vao) {
183 PLUGIN_ASSERT(device_.IsActive());
184 device_.DeleteVertexArray(plat_.vao);
185 }
186 }
187
GetPlatformData() const188 const PipelineStateObjectPlatformDataGL& GraphicsPipelineStateObjectGLES::GetPlatformData() const
189 {
190 return plat_;
191 }
192
ComputePipelineStateObjectGLES(Device & device,const GpuComputeProgram & gpuComputeProgram,const PipelineLayout & pipelineLayout,const ShaderSpecializationConstantDataView & specializationConstants)193 ComputePipelineStateObjectGLES::ComputePipelineStateObjectGLES(Device& device,
194 const GpuComputeProgram& gpuComputeProgram, const PipelineLayout& pipelineLayout,
195 const ShaderSpecializationConstantDataView& specializationConstants)
196 : ComputePipelineStateObject(), device_((DeviceGLES&)device)
197 {
198 PLUGIN_UNUSED(device_);
199 plat_.pipelineLayout = pipelineLayout;
200 const auto* source = (const GpuComputeProgramGLES*)&gpuComputeProgram;
201 plat_.computeShader = specialized_ = source->Specialize(specializationConstants);
202 PLUGIN_ASSERT(device_.IsActive());
203 const auto& shaderdata = (const GpuComputeProgramPlatformDataGL&)plat_.computeShader->GetPlatformData();
204 PLUGIN_UNUSED(shaderdata);
205 PLUGIN_ASSERT(shaderdata.program != 0);
206 }
207
~ComputePipelineStateObjectGLES()208 ComputePipelineStateObjectGLES::~ComputePipelineStateObjectGLES()
209 {
210 delete specialized_;
211 }
212
GetPlatformData() const213 const PipelineStateObjectPlatformDataGL& ComputePipelineStateObjectGLES::GetPlatformData() const
214 {
215 return plat_;
216 }
217 RENDER_END_NAMESPACE()
218