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