Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c937bc5

Browse files
brianosmanSkia Commit-Bot
authored andcommitted
Improvements to uniform handling in runtime SkSL
- Support array uniforms - Fix cases where the read head wasn't aligned in onSetData - Default to float as the CType for half. (half4 was using PMColor, and other half types required a layout(ctype...) Change-Id: I63cb1706071668de0ab80f3d812cd9ad29ff9651 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/258808 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
1 parent 425929c commit c937bc5

File tree

2 files changed

+137
-122
lines changed

2 files changed

+137
-122
lines changed

gm/runtimeshader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <stddef.h>
2424

2525
const char* gProg = R"(
26-
layout(ctype=SkRect) uniform half4 gColor;
26+
uniform half4 gColor;
2727
2828
void main(float x, float y, inout half4 color) {
2929
color = half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);

src/gpu/effects/GrSkSLFP.cpp

Lines changed: 136 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCap
5050
}
5151
}
5252

53+
static std::tuple<const SkSL::Type*, int> strip_array(const SkSL::Type* type) {
54+
int arrayCount = 0;
55+
if (type->kind() == SkSL::Type::kArray_Kind) {
56+
arrayCount = type->columns();
57+
type = &type->componentType();
58+
}
59+
return std::make_tuple(type, arrayCount);
60+
}
61+
5362
const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs,
5463
size_t inputSize) {
5564
const auto& found = fSpecializations.find(key);
@@ -60,33 +69,41 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key,
6069
std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
6170
size_t offset = 0;
6271
for (const auto& v : fInAndUniformVars) {
72+
auto [type, arrayCount] = strip_array(&v->fType);
73+
arrayCount = SkTMax(1, arrayCount);
6374
SkSL::String name(v->fName);
64-
if (&v->fType == fCompiler.context().fInt_Type.get() ||
65-
&v->fType == fCompiler.context().fShort_Type.get()) {
75+
if (type == fCompiler.context().fInt_Type.get() ||
76+
type == fCompiler.context().fShort_Type.get()) {
6677
offset = SkAlign4(offset);
67-
int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset);
68-
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
69-
offset += sizeof(int32_t);
70-
} else if (&v->fType == fCompiler.context().fFloat_Type.get() ||
71-
&v->fType == fCompiler.context().fHalf_Type.get()) {
78+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
79+
int32_t v = *(int32_t*)(((uint8_t*)inputs) + offset);
80+
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
81+
}
82+
offset += sizeof(int32_t) * arrayCount;
83+
} else if (type == fCompiler.context().fFloat_Type.get() ||
84+
type == fCompiler.context().fHalf_Type.get()) {
7285
offset = SkAlign4(offset);
73-
float v = *(float*) (((uint8_t*) inputs) + offset);
74-
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
75-
offset += sizeof(float);
76-
} else if (&v->fType == fCompiler.context().fBool_Type.get()) {
77-
bool v = *(((bool*) inputs) + offset);
78-
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
79-
offset += sizeof(bool);
80-
} else if (&v->fType == fCompiler.context().fFloat2_Type.get() ||
81-
&v->fType == fCompiler.context().fHalf2_Type.get()) {
82-
offset = SkAlign4(offset) + sizeof(float) * 2;
83-
} else if (&v->fType == fCompiler.context().fFloat3_Type.get() ||
84-
&v->fType == fCompiler.context().fHalf3_Type.get()) {
85-
offset = SkAlign4(offset) + sizeof(float) * 3;
86-
} else if (&v->fType == fCompiler.context().fFloat4_Type.get() ||
87-
&v->fType == fCompiler.context().fHalf4_Type.get()) {
88-
offset = SkAlign4(offset) + sizeof(float) * 4;
89-
} else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) {
86+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
87+
float v = *(float*)(((uint8_t*)inputs) + offset);
88+
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
89+
}
90+
offset += sizeof(float) * arrayCount;
91+
} else if (type == fCompiler.context().fBool_Type.get()) {
92+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
93+
bool v = *(((bool*)inputs) + offset);
94+
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
95+
}
96+
offset += sizeof(bool) * arrayCount;
97+
} else if (type == fCompiler.context().fFloat2_Type.get() ||
98+
type == fCompiler.context().fHalf2_Type.get()) {
99+
offset = SkAlign4(offset) + sizeof(float) * 2 * arrayCount;
100+
} else if (type == fCompiler.context().fFloat3_Type.get() ||
101+
type == fCompiler.context().fHalf3_Type.get()) {
102+
offset = SkAlign4(offset) + sizeof(float) * 3 * arrayCount;
103+
} else if (type == fCompiler.context().fFloat4_Type.get() ||
104+
type == fCompiler.context().fHalf4_Type.get()) {
105+
offset = SkAlign4(offset) + sizeof(float) * 4 * arrayCount;
106+
} else if (type == fCompiler.context().fFragmentProcessor_Type.get()) {
90107
// do nothing
91108
} else {
92109
printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str());
@@ -105,28 +122,28 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key,
105122
return result;
106123
}
107124

108-
static SkSL::Layout::CType get_ctype(const SkSL::Context& context, const SkSL::Variable& v) {
109-
SkSL::Layout::CType result = v.fModifiers.fLayout.fCType;
110-
if (result == SkSL::Layout::CType::kDefault) {
111-
if (&v.fType == context.fFloat_Type.get()) {
125+
static std::tuple<SkSL::Layout::CType, int> get_ctype(const SkSL::Context& context,
126+
const SkSL::Variable& v) {
127+
auto [type, arrayCount] = strip_array(&v.fType);
128+
SkSL::Layout::CType result = v.fModifiers.fLayout.fCType;
129+
if (result == SkSL::Layout::CType::kDefault) {
130+
if (type == context.fFloat_Type.get() || type == context.fHalf_Type.get()) {
112131
result = SkSL::Layout::CType::kFloat;
113-
} else if (&v.fType == context.fFloat2_Type.get()) {
132+
} else if (type == context.fFloat2_Type.get() || type == context.fHalf2_Type.get()) {
114133
result = SkSL::Layout::CType::kFloat2;
115-
} else if (&v.fType == context.fFloat3_Type.get()) {
134+
} else if (type == context.fFloat3_Type.get() || type == context.fHalf3_Type.get()) {
116135
result = SkSL::Layout::CType::kFloat3;
117-
} else if (&v.fType == context.fFloat4_Type.get()) {
118-
result = SkSL::Layout::CType::kSkRect;
119-
} else if (&v.fType == context.fHalf4_Type.get()) {
120-
result = SkSL::Layout::CType::kSkPMColor;
121-
} else if (&v.fType == context.fInt_Type.get()) {
136+
} else if (type == context.fFloat4_Type.get() || type == context.fHalf4_Type.get()) {
137+
result = SkSL::Layout::CType::kSkRect;
138+
} else if (type == context.fInt_Type.get()) {
122139
result = SkSL::Layout::CType::kInt32;
123-
} else if (&v.fType == context.fBool_Type.get()) {
140+
} else if (type == context.fBool_Type.get()) {
124141
result = SkSL::Layout::CType::kBool;
125142
} else {
126-
return SkSL::Layout::CType::kDefault;
143+
return std::make_tuple(SkSL::Layout::CType::kDefault, arrayCount);
127144
}
128145
}
129-
return result;
146+
return std::make_tuple(result, arrayCount);
130147
}
131148

132149
class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
@@ -241,10 +258,12 @@ class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
241258
for (const auto& v : fInAndUniformVars) {
242259
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType !=
243260
*fContext.fFragmentProcessor_Type) {
244-
fUniformHandles.push_back(args.fUniformHandler->addUniform(
261+
auto [type, arrayCount] = strip_array(&v->fType);
262+
fUniformHandles.push_back(args.fUniformHandler->addUniformArray(
245263
kFragment_GrShaderFlag,
246-
this->uniformType(v->fType),
247-
SkSL::String(v->fName).c_str()));
264+
this->uniformType(*type),
265+
SkSL::String(v->fName).c_str(),
266+
arrayCount));
248267
}
249268
}
250269
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -278,70 +297,63 @@ class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
278297
const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
279298
char* inputs = (char*) outer.fInputs.get();
280299
for (const auto& v : outer.fFactory->fInAndUniformVars) {
281-
switch (get_ctype(fContext, *v)) {
300+
auto [ctype, arrayCount] = get_ctype(fContext, *v);
301+
arrayCount = SkTMax(1, arrayCount);
302+
switch (ctype) {
282303
case SkSL::Layout::CType::kSkPMColor: {
283-
float f1 = ((uint8_t*) inputs)[offset++] / 255.0;
284-
float f2 = ((uint8_t*) inputs)[offset++] / 255.0;
285-
float f3 = ((uint8_t*) inputs)[offset++] / 255.0;
286-
float f4 = ((uint8_t*) inputs)[offset++] / 255.0;
304+
offset = SkAlign4(offset);
305+
SkSTArray<4, float, true> f;
306+
for (int i = 0; i < arrayCount * 4; ++i) {
307+
f.push_back(((uint8_t*)inputs)[offset++] / 255.0);
308+
}
287309
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
288-
pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
310+
pdman.set4fv(fUniformHandles[uniformIndex++], arrayCount, f.begin());
289311
}
290312
break;
291313
}
292314
case SkSL::Layout::CType::kFloat2: {
293315
offset = SkAlign4(offset);
294-
float f1 = *(float*) (inputs + offset);
295-
offset += sizeof(float);
296-
float f2 = *(float*) (inputs + offset);
297-
offset += sizeof(float);
316+
const float* f = (float*)(inputs + offset);
317+
offset += sizeof(float) * 2 * arrayCount;
298318
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
299-
pdman.set2f(fUniformHandles[uniformIndex++], f1, f2);
319+
pdman.set2fv(fUniformHandles[uniformIndex++], arrayCount, f);
300320
}
301321
break;
302322
}
303323
case SkSL::Layout::CType::kFloat3: {
304324
offset = SkAlign4(offset);
305-
float f1 = *(float*) (inputs + offset);
306-
offset += sizeof(float);
307-
float f2 = *(float*) (inputs + offset);
308-
offset += sizeof(float);
309-
float f3 = *(float*) (inputs + offset);
310-
offset += sizeof(float);
325+
const float* f = (float*)(inputs + offset);
326+
offset += sizeof(float) * 3 * arrayCount;
311327
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
312-
pdman.set3f(fUniformHandles[uniformIndex++], f1, f2, f3);
328+
pdman.set3fv(fUniformHandles[uniformIndex++], arrayCount, f);
313329
}
314330
break;
315331
}
316332
case SkSL::Layout::CType::kSkPMColor4f:
317333
case SkSL::Layout::CType::kSkRect: {
318334
offset = SkAlign4(offset);
319-
float f1 = *(float*) (inputs + offset);
320-
offset += sizeof(float);
321-
float f2 = *(float*) (inputs + offset);
322-
offset += sizeof(float);
323-
float f3 = *(float*) (inputs + offset);
324-
offset += sizeof(float);
325-
float f4 = *(float*) (inputs + offset);
326-
offset += sizeof(float);
335+
const float* f = (float*)(inputs + offset);
336+
offset += sizeof(float) * 4 * arrayCount;
327337
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
328-
pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
338+
pdman.set4fv(fUniformHandles[uniformIndex++], arrayCount, f);
329339
}
330340
break;
331341
}
332342
case SkSL::Layout::CType::kInt32: {
333-
int32_t i = *(int32_t*) (inputs + offset);
334-
offset += sizeof(int32_t);
343+
offset = SkAlign4(offset);
344+
int32_t* i = (int32_t*)(inputs + offset);
345+
offset += sizeof(int32_t) * arrayCount;
335346
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
336-
pdman.set1i(fUniformHandles[uniformIndex++], i);
347+
pdman.set1iv(fUniformHandles[uniformIndex++], arrayCount, i);
337348
}
338349
break;
339350
}
340351
case SkSL::Layout::CType::kFloat: {
341-
float f = *(float*) (inputs + offset);
342-
offset += sizeof(float);
352+
offset = SkAlign4(offset);
353+
float* f = (float*)(inputs + offset);
354+
offset += sizeof(float) * arrayCount;
343355
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
344-
pdman.set1f(fUniformHandles[uniformIndex++], f);
356+
pdman.set1fv(fUniformHandles[uniformIndex++], arrayCount, f);
345357
}
346358
break;
347359
}
@@ -476,56 +488,59 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
476488
if (&v->fType == context.fFragmentProcessor_Type.get()) {
477489
continue;
478490
}
479-
switch (get_ctype(context, *v)) {
480-
case SkSL::Layout::CType::kBool:
481-
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
482-
fKey += inputs[offset];
483-
b->add32(inputs[offset]);
484-
}
485-
++offset;
486-
break;
487-
case SkSL::Layout::CType::kInt32: {
488-
offset = SkAlign4(offset);
489-
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
490-
fKey += inputs[offset + 0];
491-
fKey += inputs[offset + 1];
492-
fKey += inputs[offset + 2];
493-
fKey += inputs[offset + 3];
494-
b->add32(*(int32_t*) (inputs + offset));
491+
auto [ctype, arrayCount] = get_ctype(context, *v);
492+
for (int idx = 0; idx < SkTMax(1, arrayCount); ++idx) {
493+
switch (ctype) {
494+
case SkSL::Layout::CType::kBool:
495+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
496+
fKey += inputs[offset];
497+
b->add32(inputs[offset]);
498+
}
499+
++offset;
500+
break;
501+
case SkSL::Layout::CType::kInt32: {
502+
offset = SkAlign4(offset);
503+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
504+
fKey += inputs[offset + 0];
505+
fKey += inputs[offset + 1];
506+
fKey += inputs[offset + 2];
507+
fKey += inputs[offset + 3];
508+
b->add32(*(int32_t*)(inputs + offset));
509+
}
510+
offset += sizeof(int32_t);
511+
break;
495512
}
496-
offset += sizeof(int32_t);
497-
break;
498-
}
499-
case SkSL::Layout::CType::kFloat: {
500-
offset = SkAlign4(offset);
501-
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
502-
fKey += inputs[offset + 0];
503-
fKey += inputs[offset + 1];
504-
fKey += inputs[offset + 2];
505-
fKey += inputs[offset + 3];
506-
b->add32(*(float*) (inputs + offset));
513+
case SkSL::Layout::CType::kFloat: {
514+
offset = SkAlign4(offset);
515+
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
516+
fKey += inputs[offset + 0];
517+
fKey += inputs[offset + 1];
518+
fKey += inputs[offset + 2];
519+
fKey += inputs[offset + 3];
520+
b->add32(*(float*)(inputs + offset));
521+
}
522+
offset += sizeof(float);
523+
break;
507524
}
508-
offset += sizeof(float);
509-
break;
525+
case SkSL::Layout::CType::kFloat2:
526+
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2,
527+
&offset, &fKey);
528+
break;
529+
case SkSL::Layout::CType::kFloat3:
530+
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3,
531+
&offset, &fKey);
532+
break;
533+
case SkSL::Layout::CType::kSkPMColor:
534+
case SkSL::Layout::CType::kSkPMColor4f:
535+
case SkSL::Layout::CType::kSkRect:
536+
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4,
537+
&offset, &fKey);
538+
break;
539+
default:
540+
// unsupported input var type
541+
printf("%s\n", SkSL::String(v->fType.fName).c_str());
542+
SkASSERT(false);
510543
}
511-
case SkSL::Layout::CType::kFloat2:
512-
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2,
513-
&offset, &fKey);
514-
break;
515-
case SkSL::Layout::CType::kFloat3:
516-
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3,
517-
&offset, &fKey);
518-
break;
519-
case SkSL::Layout::CType::kSkPMColor:
520-
case SkSL::Layout::CType::kSkPMColor4f:
521-
case SkSL::Layout::CType::kSkRect:
522-
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4,
523-
&offset, &fKey);
524-
break;
525-
default:
526-
// unsupported input var type
527-
printf("%s\n", SkSL::String(v->fType.fName).c_str());
528-
SkASSERT(false);
529544
}
530545
}
531546
}

0 commit comments

Comments
 (0)