1 #include "GPUDriverTestScreen.h"
2 #include "Common/Data/Text/I18n.h"
3 #include "Common/UI/View.h"
4 #include "Common/GPU/Shader.h"
5 #include "Common/GPU/ShaderWriter.h"
6
7 const uint32_t textColorOK = 0xFF30FF30;
8 const uint32_t textColorBAD = 0xFF3030FF;
9 const uint32_t bgColorOK = 0xFF106010;
10 const uint32_t bgColorBAD = 0xFF101060;
11
12 // TODO: One day, port these to use ShaderWriter.
13
14 static const std::vector<Draw::ShaderSource> fsDiscard = {
15 {ShaderLanguage::GLSL_1xx,
16 R"(
17 #ifdef GL_ES
18 precision lowp float;
19 #endif
20 #if __VERSION__ >= 130
21 #define varying in
22 #define gl_FragColor fragColor0
23 out vec4 fragColor0;
24 #endif
25 varying vec4 oColor0;
26 varying vec2 oTexCoord0;
27 uniform sampler2D Sampler0;
28 void main() {
29 #if __VERSION__ >= 130
30 vec4 color = texture(Sampler0, oTexCoord0) * oColor0;
31 #else
32 vec4 color = texture2D(Sampler0, oTexCoord0) * oColor0;
33 #endif
34 if (color.a <= 0.0)
35 discard;
36 gl_FragColor = color;
37 })"
38 },
39 {ShaderLanguage::GLSL_VULKAN,
40 R"(#version 450
41 #extension GL_ARB_separate_shader_objects : enable
42 #extension GL_ARB_shading_language_420pack : enable
43 layout(location = 0) in vec4 oColor0;
44 layout(location = 1) in vec2 oTexCoord0;
45 layout(location = 0) out vec4 fragColor0;
46 layout(set = 0, binding = 1) uniform sampler2D Sampler0;
47 void main() {
48 vec4 color = texture(Sampler0, oTexCoord0) * oColor0;
49 if (color.a <= 0.0)
50 discard;
51 fragColor0 = color;
52 })"
53 },
54 };
55
56 static const std::vector<Draw::ShaderSource> fsAdrenoLogicTest = {
57 {ShaderLanguage::GLSL_1xx,
58 R"(
59 #ifdef GL_ES
60 precision lowp float;
61 #endif
62 #if __VERSION__ >= 130
63 #define varying in
64 #define gl_FragColor fragColor0
65 out vec4 fragColor0;
66 #endif
67 varying vec4 oColor0;
68 varying vec2 oTexCoord0;
69 uniform sampler2D Sampler0;
70 void main() {
71 #if __VERSION__ >= 130
72 vec4 color = (texture(Sampler0, oTexCoord0) * oColor0).aaaa;
73 #else
74 vec4 color = (texture2D(Sampler0, oTexCoord0) * oColor0).aaaa;
75 #endif
76 color *= 2.0;
77 if (color.r < 0.002 && color.g < 0.002 && color.b < 0.002) discard;
78 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
79 })"
80 },
81 {ShaderLanguage::GLSL_VULKAN,
82 R"(#version 450
83 #extension GL_ARB_separate_shader_objects : enable
84 #extension GL_ARB_shading_language_420pack : enable
85 layout(location = 0) in vec4 oColor0;
86 layout(location = 1) in highp vec2 oTexCoord0;
87 layout(location = 0) out vec4 fragColor0;
88 layout(set = 0, binding = 1) uniform sampler2D Sampler0;
89 void main() {
90 vec4 v = texture(Sampler0, oTexCoord0).aaaa * oColor0;
91 if (v.r < 0.2 && v.g < 0.2 && v.b < 0.2) discard;
92 fragColor0 = vec4(0.0, 1.0, 0.0, 1.0);
93 })"
94 },
95 };
96
97 static const std::vector<Draw::ShaderSource> vsAdrenoLogicTest = {
98 { GLSL_1xx,
99 "#if __VERSION__ >= 130\n"
100 "#define attribute in\n"
101 "#define varying out\n"
102 "#endif\n"
103 "attribute vec3 Position;\n"
104 "attribute vec4 Color0;\n"
105 "attribute vec2 TexCoord0;\n"
106 "varying vec4 oColor0;\n"
107 "varying vec2 oTexCoord0;\n"
108 "uniform mat4 WorldViewProj;\n"
109 "void main() {\n"
110 " gl_Position = WorldViewProj * vec4(Position, 1.0);\n"
111 " oColor0 = Color0;\n"
112 " oTexCoord0 = TexCoord0;\n"
113 "}\n"
114 },
115 { ShaderLanguage::GLSL_VULKAN,
116 "#version 450\n"
117 "#extension GL_ARB_separate_shader_objects : enable\n"
118 "#extension GL_ARB_shading_language_420pack : enable\n"
119 "layout (std140, set = 0, binding = 0) uniform bufferVals {\n"
120 " mat4 WorldViewProj;\n"
121 "} myBufferVals;\n"
122 "layout (location = 0) in vec4 pos;\n"
123 "layout (location = 1) in vec4 inColor;\n"
124 "layout (location = 2) in vec2 inTexCoord;\n"
125 "layout (location = 0) out vec4 outColor;\n"
126 "layout (location = 1) out highp vec2 outTexCoord;\n"
127 "out gl_PerVertex { vec4 gl_Position; };\n"
128 "void main() {\n"
129 " outColor = inColor;\n"
130 " outTexCoord = inTexCoord;\n"
131 " gl_Position = myBufferVals.WorldViewProj * pos;\n"
132 "}\n"
133 }
134 };
135
136 static const std::vector<Draw::ShaderSource> fsFlat = {
137 {ShaderLanguage::GLSL_3xx,
138 "#ifdef GL_ES\n"
139 "precision lowp float;\n"
140 "precision highp int;\n"
141 "#endif\n"
142 "uniform sampler2D Sampler0;\n"
143 "flat in lowp vec4 oColor0;\n"
144 "in mediump vec3 oTexCoord0;\n"
145 "out vec4 fragColor0;\n"
146 "void main() {\n"
147 " vec4 t = texture(Sampler0, oTexCoord0.xy);\n"
148 " vec4 p = oColor0;\n"
149 " vec4 v = p * t;\n"
150 " fragColor0 = v;\n"
151 "}\n"
152 },
153 {ShaderLanguage::GLSL_1xx,
154 "#ifdef GL_ES\n"
155 "precision lowp float;\n"
156 "#endif\n"
157 "#if __VERSION__ >= 130\n"
158 "#define varying in\n"
159 "#define texture2D texture\n"
160 "#define gl_FragColor fragColor0\n"
161 "out vec4 fragColor0;\n"
162 "#endif\n"
163 "varying vec4 oColor0;\n"
164 "varying vec2 oTexCoord0;\n"
165 "uniform sampler2D Sampler0;\n"
166 "void main() { gl_FragColor = texture2D(Sampler0, oTexCoord0) * oColor0; }\n"
167 },
168 {ShaderLanguage::GLSL_VULKAN,
169 "#version 450\n"
170 "#extension GL_ARB_separate_shader_objects : enable\n"
171 "#extension GL_ARB_shading_language_420pack : enable\n"
172 "layout(location = 0) flat in lowp vec4 oColor0;\n"
173 "layout(location = 1) in highp vec2 oTexCoord0;\n"
174 "layout(location = 0) out vec4 fragColor0;\n"
175 "layout(set = 0, binding = 1) uniform sampler2D Sampler0;\n"
176 "void main() { fragColor0 = texture(Sampler0, oTexCoord0) * oColor0; }\n"
177 }
178 };
179
180 static const std::vector<Draw::ShaderSource> vsFlat = {
181 { GLSL_3xx,
182 "in vec3 Position;\n"
183 "in vec2 TexCoord0;\n"
184 "in lowp vec4 Color0;\n"
185 "uniform mat4 WorldViewProj;\n"
186 "flat out lowp vec4 oColor0;\n"
187 "out mediump vec3 oTexCoord0;\n"
188 "void main() {\n"
189 " oTexCoord0 = vec3(TexCoord0, 1.0);\n"
190 " oColor0 = Color0;\n"
191 " vec4 outPos = WorldViewProj * vec4(Position, 1.0);\n"
192 " gl_Position = outPos;\n"
193 "}\n"
194 },
195 { GLSL_1xx, // Doesn't actually repro the problem since flat support isn't guaranteed
196 "#if __VERSION__ >= 130\n"
197 "#define attribute in\n"
198 "#define varying out\n"
199 "#endif\n"
200 "attribute vec3 Position;\n"
201 "attribute vec4 Color0;\n"
202 "attribute vec2 TexCoord0;\n"
203 "varying vec4 oColor0;\n"
204 "varying vec2 oTexCoord0;\n"
205 "uniform mat4 WorldViewProj;\n"
206 "void main() {\n"
207 " gl_Position = WorldViewProj * vec4(Position, 1.0);\n"
208 " oColor0 = Color0;\n"
209 " oTexCoord0 = TexCoord0;\n"
210 "}\n"
211 },
212 { ShaderLanguage::GLSL_VULKAN,
213 "#version 450\n"
214 "#extension GL_ARB_separate_shader_objects : enable\n"
215 "#extension GL_ARB_shading_language_420pack : enable\n"
216 "layout (std140, set = 0, binding = 0) uniform bufferVals {\n"
217 " mat4 WorldViewProj;\n"
218 "} myBufferVals;\n"
219 "layout (location = 0) in vec4 pos;\n"
220 "layout (location = 1) in vec4 inColor;\n"
221 "layout (location = 2) in vec2 inTexCoord;\n"
222 "layout (location = 0) flat out lowp vec4 outColor;\n"
223 "layout (location = 1) out highp vec2 outTexCoord;\n"
224 "out gl_PerVertex { vec4 gl_Position; };\n"
225 "void main() {\n"
226 " outColor = inColor;\n"
227 " outTexCoord = inTexCoord;\n"
228 " gl_Position = myBufferVals.WorldViewProj * pos;\n"
229 "}\n"
230 }
231 };
232
GPUDriverTestScreen()233 GPUDriverTestScreen::GPUDriverTestScreen() {
234 using namespace Draw;
235 }
236
~GPUDriverTestScreen()237 GPUDriverTestScreen::~GPUDriverTestScreen() {
238 if (discardWriteDepthStencil_)
239 discardWriteDepthStencil_->Release();
240 if (discardWriteDepth_)
241 discardWriteDepth_->Release();
242 if (discardWriteStencil_)
243 discardWriteStencil_->Release();
244
245 if (drawTestStencilEqualDepthAlways_)
246 drawTestStencilEqualDepthAlways_->Release();
247 if (drawTestStencilNotEqualDepthAlways_)
248 drawTestStencilNotEqualDepthAlways_->Release();
249 if (drawTestStencilEqual_)
250 drawTestStencilEqual_->Release();
251 if (drawTestStencilNotEqual_)
252 drawTestStencilNotEqual_->Release();
253 if (drawTestStencilAlwaysDepthLessEqual_)
254 drawTestStencilAlwaysDepthLessEqual_->Release();
255 if (drawTestStencilAlwaysDepthGreater_)
256 drawTestStencilAlwaysDepthGreater_->Release();
257 if (drawTestDepthLessEqual_)
258 drawTestDepthLessEqual_->Release();
259 if (drawTestDepthGreater_)
260 drawTestDepthGreater_->Release();
261
262 if (discardFragShader_)
263 discardFragShader_->Release();
264
265 // Shader test
266 if (adrenoLogicDiscardPipeline_)
267 adrenoLogicDiscardPipeline_->Release();
268 if (flatShadingPipeline_)
269 flatShadingPipeline_->Release();
270
271 if (adrenoLogicDiscardFragShader_)
272 adrenoLogicDiscardFragShader_->Release();
273 if (adrenoLogicDiscardVertShader_)
274 adrenoLogicDiscardVertShader_->Release();
275 if (flatFragShader_)
276 flatFragShader_->Release();
277 if (flatVertShader_)
278 flatVertShader_->Release();
279
280 if (samplerNearest_)
281 samplerNearest_->Release();
282 }
283
CreateViews()284 void GPUDriverTestScreen::CreateViews() {
285 using namespace Draw;
286
287 if (!samplerNearest_) {
288 DrawContext *draw = screenManager()->getDrawContext();
289 SamplerStateDesc nearestDesc{};
290 samplerNearest_ = draw->CreateSamplerState(nearestDesc);
291 }
292
293 // Don't bother with views for now.
294 using namespace UI;
295 auto di = GetI18NCategory("Dialog");
296 auto cr = GetI18NCategory("PSPCredits");
297
298 AnchorLayout *anchor = new AnchorLayout();
299 root_ = anchor;
300
301 tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 30.0f, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, false));
302 anchor->Add(tabHolder_);
303 tabHolder_->AddTab("Discard", new LinearLayout(ORIENT_VERTICAL));
304 tabHolder_->AddTab("Shader", new LinearLayout(ORIENT_VERTICAL));
305
306 Choice *back = new Choice(di->T("Back"), "", false, new AnchorLayoutParams(100, WRAP_CONTENT, 10, NONE, NONE, 10));
307 back->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
308 anchor->Add(back);
309 }
310
DiscardTest()311 void GPUDriverTestScreen::DiscardTest() {
312 using namespace UI;
313 using namespace Draw;
314 if (!discardWriteDepthStencil_) {
315 DrawContext *draw = screenManager()->getDrawContext();
316
317 // Create the special shader module.
318
319 discardFragShader_ = CreateShader(draw, ShaderStage::Fragment, fsDiscard);
320
321 InputLayout *inputLayout = ui_draw2d.CreateInputLayout(draw);
322 BlendState *blendOff = draw->CreateBlendState({ false, 0xF });
323
324 // Write depth, write stencil.
325 DepthStencilStateDesc dsDesc{};
326 dsDesc.depthTestEnabled = true;
327 dsDesc.depthWriteEnabled = true;
328 dsDesc.depthCompare = Comparison::ALWAYS;
329 dsDesc.stencilEnabled = true;
330 dsDesc.front.compareMask = 0xFF;
331 dsDesc.front.compareOp = Comparison::ALWAYS;
332 dsDesc.front.passOp = StencilOp::REPLACE;
333 dsDesc.front.failOp = StencilOp::ZERO;
334 dsDesc.front.depthFailOp = StencilOp::ZERO;
335 dsDesc.front.writeMask = 0xFF;
336 dsDesc.back = dsDesc.front;
337 DepthStencilState *depthStencilWrite = draw->CreateDepthStencilState(dsDesc);
338
339 // Write only depth.
340 dsDesc.stencilEnabled = false;
341 DepthStencilState *depthWrite = draw->CreateDepthStencilState(dsDesc);
342
343 // Write only stencil.
344 dsDesc.stencilEnabled = true;
345 dsDesc.depthTestEnabled = false;
346 dsDesc.depthWriteEnabled = false; // Just in case the driver is crazy. when test is enabled, though, this should be ignored.
347 DepthStencilState *stencilWrite = draw->CreateDepthStencilState(dsDesc);
348
349 // Now for the shaders that read depth and/or stencil.
350
351 dsDesc.depthTestEnabled = true;
352 dsDesc.stencilEnabled = true;
353 dsDesc.depthCompare = Comparison::ALWAYS;
354 dsDesc.front.compareOp = Comparison::EQUAL;
355 dsDesc.back = dsDesc.front;
356 DepthStencilState *stencilEqualDepthAlways = draw->CreateDepthStencilState(dsDesc);
357
358 dsDesc.depthTestEnabled = false;
359 dsDesc.front.compareOp = Comparison::EQUAL;
360 dsDesc.back = dsDesc.front;
361 DepthStencilState *stencilEqual = draw->CreateDepthStencilState(dsDesc);
362
363 dsDesc.depthTestEnabled = true;
364 dsDesc.depthCompare = Comparison::ALWAYS;
365 dsDesc.front.compareOp = Comparison::NOT_EQUAL;
366 dsDesc.back = dsDesc.front;
367 DepthStencilState *stenciNotEqualDepthAlways = draw->CreateDepthStencilState(dsDesc);
368
369 dsDesc.depthTestEnabled = false;
370 dsDesc.front.compareOp = Comparison::NOT_EQUAL;
371 dsDesc.back = dsDesc.front;
372 DepthStencilState *stencilNotEqual = draw->CreateDepthStencilState(dsDesc);
373
374 dsDesc.stencilEnabled = true;
375 dsDesc.depthTestEnabled = true;
376 dsDesc.front.compareOp = Comparison::ALWAYS;
377 dsDesc.back = dsDesc.front;
378 dsDesc.depthCompare = Comparison::LESS_EQUAL;
379 DepthStencilState *stencilAlwaysDepthTestLessEqual = draw->CreateDepthStencilState(dsDesc);
380 dsDesc.depthCompare = Comparison::GREATER;
381 DepthStencilState *stencilAlwaysDepthTestGreater = draw->CreateDepthStencilState(dsDesc);
382
383 dsDesc.stencilEnabled = false;
384 dsDesc.depthTestEnabled = true;
385 dsDesc.depthCompare = Comparison::LESS_EQUAL;
386 DepthStencilState *depthTestLessEqual = draw->CreateDepthStencilState(dsDesc);
387 dsDesc.depthCompare = Comparison::GREATER;
388 DepthStencilState *depthTestGreater = draw->CreateDepthStencilState(dsDesc);
389
390 RasterState *rasterNoCull = draw->CreateRasterState({});
391
392 PipelineDesc discardDesc{
393 Primitive::TRIANGLE_LIST,
394 { draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), discardFragShader_ },
395 inputLayout, depthStencilWrite, blendOff, rasterNoCull, &vsColBufDesc,
396 };
397 discardWriteDepthStencil_ = draw->CreateGraphicsPipeline(discardDesc);
398 discardDesc.depthStencil = depthWrite;
399 discardWriteDepth_ = draw->CreateGraphicsPipeline(discardDesc);
400 discardDesc.depthStencil = stencilWrite;
401 discardWriteStencil_ = draw->CreateGraphicsPipeline(discardDesc);
402
403 PipelineDesc testDesc{
404 Primitive::TRIANGLE_LIST,
405 { draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), draw->GetFshaderPreset(FS_TEXTURE_COLOR_2D) },
406 inputLayout, stencilEqual, blendOff, rasterNoCull, &vsColBufDesc,
407 };
408 drawTestStencilEqual_ = draw->CreateGraphicsPipeline(testDesc);
409
410 testDesc.depthStencil = stencilEqualDepthAlways;
411 drawTestStencilEqualDepthAlways_ = draw->CreateGraphicsPipeline(testDesc);
412
413 testDesc.depthStencil = stencilNotEqual;
414 drawTestStencilNotEqual_ = draw->CreateGraphicsPipeline(testDesc);
415
416 testDesc.depthStencil = stenciNotEqualDepthAlways;
417 drawTestStencilNotEqualDepthAlways_ = draw->CreateGraphicsPipeline(testDesc);
418
419 testDesc.depthStencil = stencilAlwaysDepthTestGreater;
420 drawTestStencilAlwaysDepthGreater_ = draw->CreateGraphicsPipeline(testDesc);
421
422 testDesc.depthStencil = stencilAlwaysDepthTestLessEqual;
423 drawTestStencilAlwaysDepthLessEqual_ = draw->CreateGraphicsPipeline(testDesc);
424
425 testDesc.depthStencil = depthTestGreater;
426 drawTestDepthGreater_ = draw->CreateGraphicsPipeline(testDesc);
427
428 testDesc.depthStencil = depthTestLessEqual;
429 drawTestDepthLessEqual_ = draw->CreateGraphicsPipeline(testDesc);
430
431 inputLayout->Release();
432 blendOff->Release();
433 depthStencilWrite->Release();
434 stencilEqual->Release();
435 stencilNotEqual->Release();
436 stencilEqualDepthAlways->Release();
437 stenciNotEqualDepthAlways->Release();
438 stencilAlwaysDepthTestLessEqual->Release();
439 stencilAlwaysDepthTestGreater->Release();
440 depthTestLessEqual->Release();
441 depthTestGreater->Release();
442 rasterNoCull->Release();
443 }
444
445 UIContext &dc = *screenManager()->getUIContext();
446 Draw::DrawContext *draw = dc.GetDrawContext();
447
448 static const char * const writeModeNames[] = { "Stencil+Depth", "Stencil", "Depth" };
449 Pipeline *writePipelines[] = { discardWriteDepthStencil_, discardWriteStencil_, discardWriteDepth_ };
450 const int numWriteModes = ARRAY_SIZE(writeModeNames);
451
452 static const char * const testNames[] = { "Stenc", "Stenc+DepthA", "Depth", "StencA+Depth" };
453 Pipeline *testPipeline1[] = { drawTestStencilEqual_, drawTestStencilEqualDepthAlways_, drawTestDepthLessEqual_, drawTestStencilAlwaysDepthLessEqual_ };
454 Pipeline *testPipeline2[] = { drawTestStencilNotEqual_, drawTestStencilNotEqualDepthAlways_, drawTestDepthGreater_, drawTestStencilAlwaysDepthGreater_ };
455 const int numTests = ARRAY_SIZE(testNames);
456
457 static const bool validCombinations[numWriteModes][numTests] = {
458 {true, true, true, true},
459 {true, true, false, false},
460 {false, false, true, true},
461 };
462
463 // Don't want any fancy font texture stuff going on here, so use FLAG_DYNAMIC_ASCII everywhere!
464
465 // We draw the background at Z=0.5 and the text at Z=0.9.
466
467 // Then we draw a rectangle with a depth test or stencil test that should mask out the text.
468 // Plus a second rectangle with the opposite test.
469
470 // If everything is OK, both the background and the text should be OK.
471
472 Bounds layoutBounds = dc.GetLayoutBounds();
473
474 dc.Begin();
475 dc.SetFontScale(1.0f, 1.0f);
476 std::string apiName = screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME);
477 std::string vendor = screenManager()->getDrawContext()->GetInfoString(InfoField::VENDORSTRING);
478 std::string driver = screenManager()->getDrawContext()->GetInfoString(InfoField::DRIVER);
479 dc.DrawText(apiName.c_str(), layoutBounds.centerX(), 20, 0xFFFFFFFF, ALIGN_CENTER);
480 dc.DrawText(vendor.c_str(), layoutBounds.centerX(), 60, 0xFFFFFFFF, ALIGN_CENTER);
481 dc.DrawText(driver.c_str(), layoutBounds.centerX(), 100, 0xFFFFFFFF, ALIGN_CENTER);
482 dc.Flush();
483
484 float testW = 170.f;
485 float padding = 20.0f;
486 UI::Style style = dc.theme->itemStyle;
487
488 float y = 150;
489 for (int j = 0; j < numWriteModes; j++, y += 120.f + padding) {
490 float x = layoutBounds.x + (layoutBounds.w - (float)numTests * testW - (float)(numTests - 1) * padding) / 2.0f;
491 dc.Begin();
492 dc.DrawText(writeModeNames[j], layoutBounds.x + padding, y + 40, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
493 dc.Flush();
494 for (int i = 0; i < numTests; i++, x += testW + padding) {
495 if (!validCombinations[j][i])
496 continue;
497 dc.Begin();
498 Bounds bounds = { x, y + 40, testW, 70 };
499 dc.DrawText(testNames[i], bounds.x, y, style.fgColor, FLAG_DYNAMIC_ASCII);
500 dc.Flush();
501
502 dc.BeginPipeline(writePipelines[j], samplerNearest_);
503 // Draw the rectangle with stencil value 0, depth 0.1f and the text with stencil 0xFF, depth 0.9. Then leave 0xFF as the stencil value and draw the rectangles at depth 0.5.
504 draw->SetStencilRef(0x0);
505 dc.SetCurZ(0.1f);
506 dc.FillRect(UI::Drawable(bgColorBAD), bounds);
507 // test bounds
508 dc.Flush();
509
510 draw->SetStencilRef(0xff);
511 dc.SetCurZ(0.9f);
512 dc.DrawTextRect("TEST OK", bounds, textColorBAD, ALIGN_HCENTER | ALIGN_VCENTER | FLAG_DYNAMIC_ASCII);
513 dc.Flush();
514
515 // Draw rectangle that should result in the text
516 dc.BeginPipeline(testPipeline1[i], samplerNearest_);
517 draw->SetStencilRef(0xff);
518 dc.SetCurZ(0.5f);
519 dc.FillRect(UI::Drawable(textColorOK), bounds);
520 dc.Flush();
521
522 // Draw rectangle that should result in the bg
523 dc.BeginPipeline(testPipeline2[i], samplerNearest_);
524 draw->SetStencilRef(0xff);
525 dc.SetCurZ(0.5f);
526 dc.FillRect(UI::Drawable(bgColorOK), bounds);
527 dc.Flush();
528 }
529 }
530 dc.Flush();
531 }
532
ShaderTest()533 void GPUDriverTestScreen::ShaderTest() {
534 using namespace Draw;
535
536 UIContext &dc = *screenManager()->getUIContext();
537 Draw::DrawContext *draw = dc.GetDrawContext();
538
539 if (!adrenoLogicDiscardPipeline_) {
540 adrenoLogicDiscardFragShader_ = CreateShader(draw, ShaderStage::Fragment, fsAdrenoLogicTest);
541 adrenoLogicDiscardVertShader_ = CreateShader(draw, ShaderStage::Vertex, vsAdrenoLogicTest);
542
543 flatFragShader_ = CreateShader(draw, ShaderStage::Fragment, fsFlat);
544 flatVertShader_ = CreateShader(draw, ShaderStage::Vertex, vsFlat);
545
546 InputLayout *inputLayout = ui_draw2d.CreateInputLayout(draw);
547 // No blending used.
548 BlendState *blendOff = draw->CreateBlendState({ false, 0xF });
549
550 // No depth or stencil, we only use discard in this test.
551 DepthStencilStateDesc dsDesc{};
552 dsDesc.depthTestEnabled = false;
553 dsDesc.depthWriteEnabled = false;
554 DepthStencilState *depthStencilOff = draw->CreateDepthStencilState(dsDesc);
555
556 RasterState *rasterNoCull = draw->CreateRasterState({});
557
558 PipelineDesc adrenoLogicDiscardDesc{
559 Primitive::TRIANGLE_LIST,
560 { adrenoLogicDiscardVertShader_, adrenoLogicDiscardFragShader_ },
561 inputLayout, depthStencilOff, blendOff, rasterNoCull, &vsColBufDesc,
562 };
563 adrenoLogicDiscardPipeline_ = draw->CreateGraphicsPipeline(adrenoLogicDiscardDesc);
564
565 PipelineDesc flatDesc{
566 Primitive::TRIANGLE_LIST,
567 { flatVertShader_, flatFragShader_ },
568 inputLayout, depthStencilOff, blendOff, rasterNoCull, &vsColBufDesc,
569 };
570 flatShadingPipeline_ = draw->CreateGraphicsPipeline(flatDesc);
571
572 inputLayout->Release();
573 blendOff->Release();
574 depthStencilOff->Release();
575 rasterNoCull->Release();
576 }
577
578 Bounds layoutBounds = dc.GetLayoutBounds();
579
580 dc.Begin();
581 dc.SetFontScale(1.0f, 1.0f);
582 std::string apiName = screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME);
583 std::string vendor = screenManager()->getDrawContext()->GetInfoString(InfoField::VENDORSTRING);
584 std::string driver = screenManager()->getDrawContext()->GetInfoString(InfoField::DRIVER);
585 dc.DrawText(apiName.c_str(), layoutBounds.centerX(), 20, 0xFFFFFFFF, ALIGN_CENTER);
586 dc.DrawText(vendor.c_str(), layoutBounds.centerX(), 60, 0xFFFFFFFF, ALIGN_CENTER);
587 dc.DrawText(driver.c_str(), layoutBounds.centerX(), 100, 0xFFFFFFFF, ALIGN_CENTER);
588 dc.Flush();
589
590 float y = layoutBounds.y + 150;
591 float x = layoutBounds.x + 10;
592 dc.Begin();
593 dc.DrawText("Adreno logic", x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
594 dc.Flush();
595
596 float testW = 170.f;
597
598 Bounds bounds = { x + 200, y, testW, 70 };
599
600 // Draw rectangle that should result in the bg
601 dc.Begin();
602 dc.FillRect(UI::Drawable(bgColorOK), bounds);
603 dc.Flush();
604
605 // Draw text on it using the shader.
606 dc.BeginPipeline(adrenoLogicDiscardPipeline_, samplerNearest_);
607 dc.DrawTextRect("TEST OK", bounds, textColorOK, ALIGN_HCENTER | ALIGN_VCENTER | FLAG_DYNAMIC_ASCII);
608 dc.Flush();
609
610 y += 100;
611
612 dc.Begin();
613 dc.DrawText("Flat shaded tex", x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
614 dc.DrawText("(TEST OK if logo but no gradient!)", x + 400, y, 0xFFFFFFFF, ALIGN_LEFT);
615 dc.Flush();
616
617 bounds = { x + 200, y, 100, 100 };
618
619 // Draw rectangle that should be flat shaded
620 dc.BeginPipeline(flatShadingPipeline_, samplerNearest_);
621 // There is a "provoking vertex" difference here between GL and Vulkan when using flat shading. One gets one color, one gets the other.
622 // Wherever possible we should reconfigure the GL provoking vertex to match Vulkan, probably.
623 dc.DrawImageVGradient(ImageID("I_ICON"), 0xFFFFFFFF, 0xFF808080, bounds);
624 dc.Flush();
625
626 y += 120;
627
628 dc.Begin();
629 dc.DrawText("Test done", x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
630 dc.Flush();
631 }
632
633
render()634 void GPUDriverTestScreen::render() {
635 using namespace Draw;
636 UIScreen::render();
637
638 switch (tabHolder_->GetCurrentTab()) {
639 case 0:
640 DiscardTest();
641 break;
642 case 1:
643 ShaderTest();
644 break;
645 }
646 }
647