Skip to content

Commit 987a331

Browse files
committed
[Testbed] Added TextureStrides test to Testbed.
- Tests texture creation with a row stride. - Also unify parameters for background color in tests.
1 parent 5ac042b commit 987a331

11 files changed

+197
-20
lines changed
50.8 KB
Loading
23.6 KB
Loading

tests/Testbed/TestbedContext.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ unsigned TestbedContext::RunAllTests()
344344
RUN_TEST( CommandBufferSecondary );
345345
RUN_TEST( TriangleStripCutOff );
346346
RUN_TEST( TextureViews );
347+
RUN_TEST( TextureStrides );
347348
RUN_TEST( Uniforms );
348349
RUN_TEST( ShadowMapping );
349350
RUN_TEST( ViewportAndScissor );
@@ -1050,14 +1051,10 @@ void TestbedContext::CreatePipelineLayouts()
10501051

10511052
layouts[PipelineTextured] = renderer->CreatePipelineLayout(
10521053
Parse(
1053-
HasCombinedSamplers()
1054-
? "cbuffer(Scene@1):vert:frag,"
1055-
"texture(colorMap@2):frag,"
1056-
"sampler(2):frag,"
1057-
:
1058-
"cbuffer(Scene@1):vert:frag,"
1059-
"texture(colorMap@2):frag,"
1060-
"sampler(linearSampler@3):frag,"
1054+
"cbuffer(Scene@1):vert:frag,"
1055+
"texture(colorMap@2):frag,"
1056+
"sampler(linearSampler@3):frag,"
1057+
"sampler<colorMap, linearSampler>(colorMap@2),"
10611058
)
10621059
);
10631060
}

tests/Testbed/TestbedContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ class TestbedContext
310310

311311
const std::string moduleName;
312312
const Options opt;
313+
const LLGL::ClearValue bgColorDarkBlue = { 0.2f, 0.2f, 0.4f, 1.0f };
314+
const LLGL::ClearValue bgColorLightBlue = { 127.0f/255.0f, 127.0f/255.0f, 1.0f, 1.0f };
313315

314316
unsigned failures = 0;
315317

tests/Testbed/UnitTests/DeclTests.inl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ DECL_TEST( BlendStates );
7676
DECL_TEST( DualSourceBlending );
7777
DECL_TEST( TriangleStripCutOff );
7878
DECL_TEST( TextureViews );
79+
DECL_TEST( TextureStrides );
7980
DECL_TEST( Uniforms );
8081
DECL_TEST( ShadowMapping );
8182
DECL_TEST( ViewportAndScissor );

tests/Testbed/UnitTests/TestBlendStates.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ DEF_TEST( BlendStates )
9292
const IndexedTriangleMesh& mesh = models[ModelRect];
9393

9494
constexpr float offset = 0.16f;
95-
constexpr float bgColor[4] = { 127.0f/255.0f, 127.0f/255.0f, 1.0f, 1.0f };
9695

9796
Texture* readbackTex = nullptr;
9897

@@ -104,7 +103,7 @@ DEF_TEST( BlendStates )
104103
cmdBuffer->BeginRenderPass(*swapChain);
105104
{
106105
// Draw scene
107-
cmdBuffer->Clear(ClearFlags::Color, ClearValue{ bgColor });
106+
cmdBuffer->Clear(ClearFlags::Color, bgColorLightBlue);
108107

109108
for_range(i, numBlendOps)
110109
{

tests/Testbed/UnitTests/TestImageConversions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ DEF_RITEST( ImageConversions )
3131

3232
auto TestConversion = [&](const std::string& filename, unsigned threadCount, double& outTime) -> TestResult
3333
{
34-
Image img = TestbedContext::LoadImageFromFile(imagePath + filename);
34+
Image img = TestbedContext::LoadImageFromFile(imagePath + filename, opt.verbose);
3535

3636
const Image imgCopy = img;
3737

tests/Testbed/UnitTests/TestStreamOutput.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,6 @@ DEF_TEST( StreamOutput )
208208
// Initialize scene constants
209209
const float rotation = static_cast<float>(frame) * 90.0f / static_cast<float>(numFrames - 1);
210210

211-
constexpr float bgColor[4] = { 0.2f, 0.2f, 0.4f, 1.0f };
212-
213211
// Initialize scene settings
214212
const float frameTransition = static_cast<float>(frame) / static_cast<float>(numFrames - 1);
215213

@@ -244,7 +242,7 @@ DEF_TEST( StreamOutput )
244242

245243
cmdBuffer->BeginRenderPass(*swapChain);
246244
{
247-
cmdBuffer->Clear(ClearFlags::ColorDepth, ClearValue{ bgColor });
245+
cmdBuffer->Clear(ClearFlags::ColorDepth, bgColorDarkBlue);
248246
cmdBuffer->SetViewport(opt.resolution);
249247

250248
int currentSOSwapBuffer = 0;
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* TestTextureStrides.cpp
3+
*
4+
* Copyright (c) 2015 Lukas Hermanns. All rights reserved.
5+
* Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt).
6+
*/
7+
8+
#include "Testbed.h"
9+
#include <LLGL/Utils/Parse.h>
10+
#include <Gauss/Translate.h>
11+
#include <Gauss/Rotate.h>
12+
#include <Gauss/Scale.h>
13+
14+
15+
/*
16+
Test creating two textures from the same image source using row strides. Then render them onto two separate cubes.
17+
First frame:
18+
Create textures with *half* row stride, this will result in interleaved rows,
19+
i.e. row 0 from left side, row 1 from right side, row 2 from left side again, etc.
20+
Rendering this texture will create the "moire" effect, which is acceptable here.
21+
Second frame:
22+
Create textures with full row stride, this will result in a cutoff image as if only a region was copied from the image.
23+
*/
24+
DEF_TEST( TextureStrides )
25+
{
26+
static TestResult result = TestResult::Passed;
27+
static PipelineState* pso;
28+
static PipelineLayout* psoLayout;
29+
30+
constexpr unsigned numFrames = 2;
31+
32+
if (frame == 0)
33+
{
34+
result = TestResult::Passed;
35+
36+
if (shaders[VSTextured] == nullptr || shaders[PSTextured] == nullptr)
37+
{
38+
Log::Errorf("Missing shaders for backend\n");
39+
return TestResult::FailedErrors;
40+
}
41+
42+
// Create graphics PSO
43+
GraphicsPipelineDescriptor psoDesc;
44+
{
45+
psoDesc.debugName = "TextureStrides.PSO";
46+
psoDesc.pipelineLayout = layouts[PipelineTextured];
47+
psoDesc.renderPass = swapChain->GetRenderPass();
48+
psoDesc.vertexShader = shaders[VSTextured];
49+
psoDesc.fragmentShader = shaders[PSTextured];
50+
psoDesc.depth.testEnabled = true;
51+
psoDesc.depth.writeEnabled = true;
52+
psoDesc.rasterizer.cullMode = CullMode::Back;
53+
}
54+
CREATE_GRAPHICS_PSO_EXT(pso, psoDesc, psoDesc.debugName);
55+
}
56+
57+
// Create primary texture and two with different stride/offset
58+
const std::string imagePath = "../Media/Textures/";
59+
Image image = TestbedContext::LoadImageFromFile(imagePath + "Grid10x10.png", opt.verbose);
60+
61+
ImageView imageViewA;
62+
{
63+
imageViewA.format = image.GetFormat();
64+
imageViewA.dataType = image.GetDataType();
65+
imageViewA.data = image.GetData();
66+
imageViewA.dataSize = image.GetDataSize();
67+
imageViewA.rowStride = (frame == 0 ? image.GetRowStride()/2 : image.GetRowStride());
68+
}
69+
TextureDescriptor texADesc;
70+
{
71+
texADesc.debugName = "texA-strides";
72+
texADesc.format = Format::RGBA8UNorm;
73+
texADesc.extent.width = image.GetExtent().width/2;
74+
texADesc.extent.height = image.GetExtent().height;
75+
texADesc.extent.depth = 1;
76+
texADesc.mipLevels = 1;
77+
}
78+
CREATE_TEXTURE(texA, texADesc, texADesc.debugName, &imageViewA);
79+
80+
const char* imageDataBytes = static_cast<const char*>(image.GetData());
81+
const std::ptrdiff_t imageBOffset = (frame == 0 ? image.GetDataSize()/2 : image.GetRowStride()/2);
82+
83+
ImageView imageViewB;
84+
{
85+
imageViewB.format = image.GetFormat();
86+
imageViewB.dataType = image.GetDataType();
87+
imageViewB.data = imageDataBytes + imageBOffset;
88+
imageViewB.dataSize = image.GetDataSize() - imageBOffset;
89+
imageViewB.rowStride = (frame == 0 ? image.GetRowStride()/2 : image.GetRowStride());
90+
}
91+
TextureDescriptor texBDesc;
92+
{
93+
texBDesc.debugName = "texB-strides";
94+
texBDesc.format = Format::RGBA8UNorm;
95+
texBDesc.extent.width = image.GetExtent().width/2;
96+
texBDesc.extent.height = image.GetExtent().height;
97+
texBDesc.extent.depth = 1;
98+
texBDesc.mipLevels = 1;
99+
}
100+
CREATE_TEXTURE(texB, texBDesc, texBDesc.debugName, &imageViewB);
101+
102+
// Initialize scene constants
103+
sceneConstants = SceneConstants{};
104+
105+
sceneConstants.vpMatrix = projection;
106+
107+
auto TransformWorldMatrixAndUpdateCbuffer = [this](Gs::Matrix4f& wMatrix, float posX, float turn)
108+
{
109+
wMatrix.LoadIdentity();
110+
Gs::Translate(wMatrix, Gs::Vector3f{ posX, 0.0f, 3.5f });
111+
Gs::RotateFree(wMatrix, Gs::Vector3f{ 0, 1, 0 }, Gs::Deg2Rad(turn));
112+
Gs::Scale(wMatrix, Gs::Vector3f{ 0.5f });
113+
114+
cmdBuffer->UpdateBuffer(*sceneCbuffer, 0, &sceneConstants, sizeof(sceneConstants));
115+
};
116+
117+
// Render scene
118+
Texture* readbackTex = nullptr;
119+
120+
const IndexedTriangleMesh& mesh = models[ModelCube];
121+
122+
cmdBuffer->Begin();
123+
{
124+
// Graphics can be set inside and outside a render pass, so test binding this PSO outside the render pass
125+
cmdBuffer->SetVertexBuffer(*meshBuffer);
126+
cmdBuffer->SetIndexBuffer(*meshBuffer, Format::R32UInt, mesh.indexBufferOffset);
127+
cmdBuffer->SetPipelineState(*pso);
128+
129+
cmdBuffer->BeginRenderPass(*swapChain);
130+
{
131+
// Draw scene
132+
cmdBuffer->Clear(ClearFlags::ColorDepth, bgColorDarkBlue);
133+
cmdBuffer->SetViewport(opt.resolution);
134+
cmdBuffer->SetResource(0, *sceneCbuffer);
135+
cmdBuffer->SetResource(2, *samplers[SamplerNearestClamp]);
136+
137+
// Draw left cube
138+
TransformWorldMatrixAndUpdateCbuffer(sceneConstants.wMatrix, -1.0f, +35.0f);
139+
cmdBuffer->SetResource(1, *texA);
140+
141+
cmdBuffer->DrawIndexed(mesh.numIndices, 0);
142+
143+
// Draw right cube
144+
TransformWorldMatrixAndUpdateCbuffer(sceneConstants.wMatrix, +1.0f, -35.0f);
145+
cmdBuffer->SetResource(1, *texB);
146+
147+
cmdBuffer->DrawIndexed(mesh.numIndices, 0);
148+
149+
// Capture framebuffer
150+
readbackTex = CaptureFramebuffer(*cmdBuffer, swapChain->GetColorFormat(), opt.resolution);
151+
}
152+
cmdBuffer->EndRenderPass();
153+
}
154+
cmdBuffer->End();
155+
156+
// Match entire color buffer and create delta heat map
157+
const std::string colorBufferName = "TextureStrides_Frame" + std::to_string(frame);
158+
159+
SaveCapture(readbackTex, colorBufferName);
160+
161+
constexpr int threshold = 20; // High threshold because of nearest texture filter
162+
constexpr unsigned tolerance = 100; // High tolerance because of nearest texture filter
163+
const DiffResult diff = DiffImages(colorBufferName, threshold, tolerance);
164+
165+
// Evaluate readback result and tolerate 5 pixel that are beyond the threshold due to GPU differences with the reinterpretation of pixel formats
166+
TestResult intermediateResult = diff.Evaluate("texture strides", frame);
167+
if (intermediateResult != TestResult::Passed)
168+
result = intermediateResult;
169+
170+
renderer->Release(*texA);
171+
renderer->Release(*texB);
172+
173+
if (intermediateResult == TestResult::Passed || opt.greedy)
174+
{
175+
if (frame + 1 < numFrames)
176+
return TestResult::Continue;
177+
}
178+
179+
// Clear resources
180+
renderer->Release(*pso);
181+
182+
return result;
183+
}
184+

tests/Testbed/UnitTests/TestTextureViews.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@ DEF_TEST( TextureViews )
110110
// Render scene
111111
const IndexedTriangleMesh& mesh = models[ModelRect];
112112

113-
constexpr float bgColor[4] = { 127.0f/255.0f, 127.0f/255.0f, 1.0f, 1.0f };
114-
115113
Texture* readbackTex = nullptr;
116114

117115
cmdBuffer->Begin();
@@ -124,7 +122,7 @@ DEF_TEST( TextureViews )
124122
cmdBuffer->BeginRenderPass(*swapChain);
125123
{
126124
// Draw scene
127-
cmdBuffer->Clear(ClearFlags::Color, ClearValue{ bgColor });
125+
cmdBuffer->Clear(ClearFlags::Color, bgColorLightBlue);
128126

129127
// Bind PSO with current blend states
130128
cmdBuffer->SetPipelineState(*pso);

0 commit comments

Comments
 (0)