1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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 "PixelProcessor.hpp"
16
17#include "Primitive.hpp"
18#include "Pipeline/PixelProgram.hpp"
19#include "Pipeline/Constants.hpp"
20#include "Vulkan/VkDebug.hpp"
21#include "Vulkan/VkImageView.hpp"
22
23#include <cstring>
24
25namespace sw
26{
27 uint32_t PixelProcessor::States::computeHash()
28 {
29 uint32_t *state = reinterpret_cast<uint32_t*>(this);
30 uint32_t hash = 0;
31
32 for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
33 {
34 hash ^= state[i];
35 }
36
37 return hash;
38 }
39
40 bool PixelProcessor::State::operator==(const State &state) const
41 {
42 if(hash != state.hash)
43 {
44 return false;
45 }
46
47 static_assert(is_memcmparable<State>::value, "Cannot memcmp State");
48 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
49 }
50
51 PixelProcessor::PixelProcessor()
52 {
53 routineCache = nullptr;
54 setRoutineCacheSize(1024);
55 }
56
57 PixelProcessor::~PixelProcessor()
58 {
59 delete routineCache;
60 routineCache = nullptr;
61 }
62
63 void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
64 {
65 // TODO(b/140935644): Compact into generic function, cheack if clamp is required
66 factor.blendConstant4W[0][0] =
67 factor.blendConstant4W[0][1] =
68 factor.blendConstant4W[0][2] =
69 factor.blendConstant4W[0][3] = static_cast<uint16_t>(iround(65535.0f * blendConstant.r));
70
71 factor.blendConstant4W[1][0] =
72 factor.blendConstant4W[1][1] =
73 factor.blendConstant4W[1][2] =
74 factor.blendConstant4W[1][3] = static_cast<uint16_t>(iround(65535.0f * blendConstant.g));
75
76 factor.blendConstant4W[2][0] =
77 factor.blendConstant4W[2][1] =
78 factor.blendConstant4W[2][2] =
79 factor.blendConstant4W[2][3] = static_cast<uint16_t>(iround(65535.0f * blendConstant.b));
80
81 factor.blendConstant4W[3][0] =
82 factor.blendConstant4W[3][1] =
83 factor.blendConstant4W[3][2] =
84 factor.blendConstant4W[3][3] = static_cast<uint16_t>(iround(65535.0f * blendConstant.a));
85
86 factor.invBlendConstant4W[0][0] =
87 factor.invBlendConstant4W[0][1] =
88 factor.invBlendConstant4W[0][2] =
89 factor.invBlendConstant4W[0][3] = 0xFFFFu - factor.blendConstant4W[0][0];
90
91 factor.invBlendConstant4W[1][0] =
92 factor.invBlendConstant4W[1][1] =
93 factor.invBlendConstant4W[1][2] =
94 factor.invBlendConstant4W[1][3] = 0xFFFFu - factor.blendConstant4W[1][0];
95
96 factor.invBlendConstant4W[2][0] =
97 factor.invBlendConstant4W[2][1] =
98 factor.invBlendConstant4W[2][2] =
99 factor.invBlendConstant4W[2][3] = 0xFFFFu - factor.blendConstant4W[2][0];
100
101 factor.invBlendConstant4W[3][0] =
102 factor.invBlendConstant4W[3][1] =
103 factor.invBlendConstant4W[3][2] =
104 factor.invBlendConstant4W[3][3] = 0xFFFFu - factor.blendConstant4W[3][0];
105
106 factor.blendConstant4F[0][0] =
107 factor.blendConstant4F[0][1] =
108 factor.blendConstant4F[0][2] =
109 factor.blendConstant4F[0][3] = blendConstant.r;
110
111 factor.blendConstant4F[1][0] =
112 factor.blendConstant4F[1][1] =
113 factor.blendConstant4F[1][2] =
114 factor.blendConstant4F[1][3] = blendConstant.g;
115
116 factor.blendConstant4F[2][0] =
117 factor.blendConstant4F[2][1] =
118 factor.blendConstant4F[2][2] =
119 factor.blendConstant4F[2][3] = blendConstant.b;
120
121 factor.blendConstant4F[3][0] =
122 factor.blendConstant4F[3][1] =
123 factor.blendConstant4F[3][2] =
124 factor.blendConstant4F[3][3] = blendConstant.a;
125
126 factor.invBlendConstant4F[0][0] =
127 factor.invBlendConstant4F[0][1] =
128 factor.invBlendConstant4F[0][2] =
129 factor.invBlendConstant4F[0][3] = 1 - blendConstant.r;
130
131 factor.invBlendConstant4F[1][0] =
132 factor.invBlendConstant4F[1][1] =
133 factor.invBlendConstant4F[1][2] =
134 factor.invBlendConstant4F[1][3] = 1 - blendConstant.g;
135
136 factor.invBlendConstant4F[2][0] =
137 factor.invBlendConstant4F[2][1] =
138 factor.invBlendConstant4F[2][2] =
139 factor.invBlendConstant4F[2][3] = 1 - blendConstant.b;
140
141 factor.invBlendConstant4F[3][0] =
142 factor.invBlendConstant4F[3][1] =
143 factor.invBlendConstant4F[3][2] =
144 factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
145 }
146
147 void PixelProcessor::setRoutineCacheSize(int cacheSize)
148 {
149 delete routineCache;
150 routineCache = new RoutineCacheType(clamp(cacheSize, 1, 65536));
151 }
152
153 const PixelProcessor::State PixelProcessor::update(const Context* context) const
154 {
155 State state;
156
157 if(context->pixelShader)
158 {
159 state.shaderID = context->pixelShader->getSerialID();
160 }
161 else
162 {
163 state.shaderID = 0;
164 }
165
166 state.alphaToCoverage = context->alphaToCoverage;
167 state.depthWriteEnable = context->depthWriteActive();
168
169 if(context->stencilActive())
170 {
171 state.stencilActive = true;
172 state.frontStencil = context->frontStencil;
173 state.backStencil = context->backStencil;
174 }
175
176 if(context->depthBufferActive())
177 {
178 state.depthTestActive = true;
179 state.depthCompareMode = context->depthCompareMode;
180 state.quadLayoutDepthBuffer = context->depthBuffer->getFormat().hasQuadLayout();
181 state.depthFormat = context->depthBuffer->getFormat();
182 }
183
184 state.occlusionEnabled = context->occlusionEnabled;
185 state.depthClamp = (context->depthBias != 0.0f) || (context->slopeDepthBias != 0.0f);
186
187 for(int i = 0; i < RENDERTARGETS; i++)
188 {
189 state.colorWriteMask |= context->colorWriteActive(i) << (4 * i);
190 state.targetFormat[i] = context->renderTargetInternalFormat(i);
191 state.blendState[i] = context->getBlendState(i);
192 }
193
194 state.multiSample = static_cast<unsigned int>(context->sampleCount);
195 state.multiSampleMask = context->multiSampleMask;
196
197 if(state.multiSample > 1 && context->pixelShader)
198 {
199 state.centroid = context->pixelShader->getModes().NeedsCentroid;
200 }
201
202 state.frontFace = context->frontFace;
203
204 state.hash = state.computeHash();
205
206 return state;
207 }
208
209 PixelProcessor::RoutineType PixelProcessor::routine(const State &state,
210 vk::PipelineLayout const *pipelineLayout,
211 SpirvShader const *pixelShader,
212 const vk::DescriptorSet::Bindings &descriptorSets)
213 {
214 auto routine = routineCache->query(state);
215
216 if(!routine)
217 {
218 QuadRasterizer *generator = new PixelProgram(state, pipelineLayout, pixelShader, descriptorSets);
219 generator->generate();
220 routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
221 delete generator;
222
223 routineCache->add(state, routine);
224 }
225
226 return routine;
227 }
228}
229