1 // Copyright 2018 The Amber Authors.
2 //
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 #include "src/executor.h"
16
17 #include <cassert>
18 #include <string>
19 #include <utility>
20 #include <vector>
21
22 #include "src/engine.h"
23 #include "src/make_unique.h"
24 #include "src/script.h"
25 #include "src/shader_compiler.h"
26
27 namespace amber {
28
29 Executor::Executor() = default;
30
31 Executor::~Executor() = default;
32
CompileShaders(const amber::Script * script,const ShaderMap & shader_map,Options * options)33 Result Executor::CompileShaders(const amber::Script* script,
34 const ShaderMap& shader_map,
35 Options* options) {
36 for (auto& pipeline : script->GetPipelines()) {
37 for (auto& shader_info : pipeline->GetShaders()) {
38 std::string target_env = shader_info.GetShader()->GetTargetEnv();
39 if (target_env.empty())
40 target_env = script->GetSpvTargetEnv();
41
42 ShaderCompiler sc(target_env, options->disable_spirv_validation,
43 script->GetVirtualFiles());
44
45 Result r;
46 std::vector<uint32_t> data;
47 std::tie(r, data) = sc.Compile(pipeline.get(), &shader_info, shader_map);
48 if (!r.IsSuccess())
49 return r;
50
51 shader_info.SetData(std::move(data));
52 }
53 }
54 return {};
55 }
56
Execute(Engine * engine,const amber::Script * script,const ShaderMap & shader_map,Options * options,Delegate * delegate)57 Result Executor::Execute(Engine* engine,
58 const amber::Script* script,
59 const ShaderMap& shader_map,
60 Options* options,
61 Delegate* delegate) {
62 engine->SetEngineData(script->GetEngineData());
63
64 if (!script->GetPipelines().empty()) {
65 Result r = CompileShaders(script, shader_map, options);
66 if (!r.IsSuccess())
67 return r;
68
69 // OpenCL specific pipeline updates.
70 for (auto& pipeline : script->GetPipelines()) {
71 r = pipeline->UpdateOpenCLBufferBindings();
72 if (!r.IsSuccess())
73 return r;
74 r = pipeline->GenerateOpenCLPodBuffers();
75 if (!r.IsSuccess())
76 return r;
77 r = pipeline->GenerateOpenCLLiteralSamplers();
78 if (!r.IsSuccess())
79 return r;
80 r = pipeline->GenerateOpenCLPushConstants();
81 if (!r.IsSuccess())
82 return r;
83 }
84
85 for (auto& pipeline : script->GetPipelines()) {
86 r = engine->CreatePipeline(pipeline.get());
87 if (!r.IsSuccess())
88 return r;
89 }
90 }
91
92 if (options->execution_type == ExecutionType::kPipelineCreateOnly)
93 return {};
94
95 // Process Commands
96 for (const auto& cmd : script->GetCommands()) {
97 if (delegate && delegate->LogExecuteCalls()) {
98 delegate->Log(std::to_string(cmd->GetLine()) + ": " + cmd->ToString());
99 }
100
101 Result r = ExecuteCommand(engine, cmd.get());
102 if (!r.IsSuccess())
103 return r;
104 }
105 return {};
106 }
107
ExecuteCommand(Engine * engine,Command * cmd)108 Result Executor::ExecuteCommand(Engine* engine, Command* cmd) {
109 if (cmd->IsProbe()) {
110 auto* buffer = cmd->AsProbe()->GetBuffer();
111 assert(buffer);
112
113 Format* fmt = buffer->GetFormat();
114 return verifier_.Probe(cmd->AsProbe(), fmt, buffer->GetElementStride(),
115 buffer->GetRowStride(), buffer->GetWidth(),
116 buffer->GetHeight(), buffer->ValuePtr()->data());
117 }
118 if (cmd->IsProbeSSBO()) {
119 auto probe_ssbo = cmd->AsProbeSSBO();
120
121 const auto* buffer = cmd->AsProbe()->GetBuffer();
122 assert(buffer);
123
124 return verifier_.ProbeSSBO(probe_ssbo, buffer->ElementCount(),
125 buffer->ValuePtr()->data());
126 }
127 if (cmd->IsClear())
128 return engine->DoClear(cmd->AsClear());
129 if (cmd->IsClearColor())
130 return engine->DoClearColor(cmd->AsClearColor());
131 if (cmd->IsClearDepth())
132 return engine->DoClearDepth(cmd->AsClearDepth());
133 if (cmd->IsClearStencil())
134 return engine->DoClearStencil(cmd->AsClearStencil());
135 if (cmd->IsCompareBuffer()) {
136 auto compare = cmd->AsCompareBuffer();
137 auto buffer_1 = compare->GetBuffer1();
138 auto buffer_2 = compare->GetBuffer2();
139 switch (compare->GetComparator()) {
140 case CompareBufferCommand::Comparator::kRmse:
141 return buffer_1->CompareRMSE(buffer_2, compare->GetTolerance());
142 case CompareBufferCommand::Comparator::kHistogramEmd:
143 return buffer_1->CompareHistogramEMD(buffer_2, compare->GetTolerance());
144 case CompareBufferCommand::Comparator::kEq:
145 return buffer_1->IsEqual(buffer_2);
146 }
147 }
148 if (cmd->IsCopy()) {
149 auto copy = cmd->AsCopy();
150 auto buffer_from = copy->GetBufferFrom();
151 auto buffer_to = copy->GetBufferTo();
152 return buffer_from->CopyTo(buffer_to);
153 }
154 if (cmd->IsDrawRect())
155 return engine->DoDrawRect(cmd->AsDrawRect());
156 if (cmd->IsDrawGrid())
157 return engine->DoDrawGrid(cmd->AsDrawGrid());
158 if (cmd->IsDrawArrays())
159 return engine->DoDrawArrays(cmd->AsDrawArrays());
160 if (cmd->IsCompute())
161 return engine->DoCompute(cmd->AsCompute());
162 if (cmd->IsEntryPoint())
163 return engine->DoEntryPoint(cmd->AsEntryPoint());
164 if (cmd->IsPatchParameterVertices())
165 return engine->DoPatchParameterVertices(cmd->AsPatchParameterVertices());
166 if (cmd->IsBuffer())
167 return engine->DoBuffer(cmd->AsBuffer());
168 if (cmd->IsRepeat()) {
169 for (uint32_t i = 0; i < cmd->AsRepeat()->GetCount(); ++i) {
170 for (const auto& sub_cmd : cmd->AsRepeat()->GetCommands()) {
171 Result r = ExecuteCommand(engine, sub_cmd.get());
172 if (!r.IsSuccess())
173 return r;
174 }
175 }
176 return {};
177 }
178 return Result("Unknown command type: " +
179 std::to_string(static_cast<uint32_t>(cmd->GetType())));
180 }
181
182 } // namespace amber
183