Compare commits
1 Commits
validation
...
pf/backend
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e32e6cf2a |
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "BackendTest.h"
|
#include "BackendTest.h"
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
#include <utils/Hash.h>
|
#include <utils/Hash.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -149,50 +150,59 @@ void BackendTest::renderTriangle(Handle<HwRenderTarget> renderTarget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BackendTest::readPixelsAndAssertHash(const char* testName, size_t width, size_t height,
|
void BackendTest::readPixelsAndAssertHash(const char* testName, size_t width, size_t height,
|
||||||
Handle<HwRenderTarget> rt, uint32_t expectedHash, bool exportScreenshot) {
|
Handle<HwRenderTarget> rt, uint32_t const expectedHash, bool const exportScreenshot) {
|
||||||
void* buffer = calloc(1, width * height * 4);
|
auto img = getRenderTargetRGB(rt, width, height);
|
||||||
|
uint32_t hash = computeImageHash(img);
|
||||||
|
|
||||||
struct Capture {
|
if (exportScreenshot) {
|
||||||
uint32_t expectedHash;
|
writeImage(img, width, height, utils::CString(testName));
|
||||||
char* name;
|
}
|
||||||
bool exportScreenshot;
|
ASSERT_EQ(hash, expectedHash) << testName << " failed: hashes do not match." << std::endl;
|
||||||
size_t width, height;
|
|
||||||
};
|
|
||||||
auto* c = new Capture();
|
|
||||||
c->expectedHash = expectedHash;
|
|
||||||
c->name = strdup(testName);
|
|
||||||
c->exportScreenshot = exportScreenshot;
|
|
||||||
c->width = width;
|
|
||||||
c->height = height;
|
|
||||||
|
|
||||||
PixelBufferDescriptor pbd(buffer, width * height * 4, PixelDataFormat::RGBA, PixelDataType::UBYTE,
|
|
||||||
1, 0, 0, width, [](void* buffer, size_t size, void* user) {
|
|
||||||
auto* c = (Capture*)user;
|
|
||||||
|
|
||||||
// Export a screenshot, if requested.
|
|
||||||
if (c->exportScreenshot) {
|
|
||||||
#ifndef IOS
|
|
||||||
LinearImage image(c->width, c->height, 4);
|
|
||||||
image = toLinearWithAlpha<uint8_t>(c->width, c->height, c->width * 4,
|
|
||||||
(uint8_t*) buffer);
|
|
||||||
const std::string png = std::string(c->name) + ".png";
|
|
||||||
std::ofstream outputStream(png.c_str(), std::ios::binary | std::ios::trunc);
|
|
||||||
ImageEncoder::encode(outputStream, ImageEncoder::Format::PNG, image, "",
|
|
||||||
png);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hash the contents of the buffer and check that they match.
|
|
||||||
uint32_t hash = utils::hash::murmur3((const uint32_t*) buffer, size / 4, 0);
|
|
||||||
ASSERT_EQ(hash, c->expectedHash) << c->name << " failed: hashes do not match." << std::endl;
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
free(c->name);
|
|
||||||
free(c);
|
|
||||||
}, (void*)c);
|
|
||||||
getDriverApi().readPixels(rt, 0, 0, width, height, std::move(pbd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BackendTest::writeImage(utils::FixedCapacityVector<uint8_t> img, size_t w, size_t h,
|
||||||
|
utils::CString const& fname) {
|
||||||
|
constexpr size_t MAX_FNAME_LEN = 50;
|
||||||
|
constexpr size_t FNAME_EXT_LEN = 4;
|
||||||
|
constexpr size_t TOTAL_LEN = MAX_FNAME_LEN + FNAME_EXT_LEN + 1;
|
||||||
|
char buf[TOTAL_LEN];
|
||||||
|
|
||||||
|
ASSERT_PRECONDITION(fname.size() <= MAX_FNAME_LEN, "File name %s is too long", fname.c_str());
|
||||||
|
|
||||||
|
snprintf(buf, TOTAL_LEN, "%s.png", fname.c_str());
|
||||||
|
|
||||||
|
#ifndef IOS
|
||||||
|
LinearImage image(w, h, 4);
|
||||||
|
image = toLinearWithAlpha<uint8_t>(w, h, w * 4, img.data());
|
||||||
|
std::ofstream pngstrm(buf, std::ios::binary | std::ios::trunc);
|
||||||
|
ImageEncoder::encode(pngstrm, ImageEncoder::Format::PNG, image, "", buf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::FixedCapacityVector<uint8_t> BackendTest::getRenderTarget(
|
||||||
|
Handle<HwRenderTarget> rt, size_t width, size_t height, PixelDataFormat format,
|
||||||
|
PixelDataType dataType) {
|
||||||
|
auto& api = getDriverApi();
|
||||||
|
size_t const size = width * height * 4;
|
||||||
|
utils::FixedCapacityVector<uint8_t> result(size);
|
||||||
|
PixelBufferDescriptor pb(result.data(), size, format, dataType);
|
||||||
|
api.readPixels(rt, 0, 0, width, height, std::move(pb));
|
||||||
|
flushAndWait();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BackendTest::computeImageHash(utils::FixedCapacityVector<uint8_t> const& img) {
|
||||||
|
return utils::hash::murmur3((uint32_t*) img.data(), img.size() / 4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::FixedCapacityVector<uint8_t> BackendTest::getRenderTargetRGB(
|
||||||
|
Handle<HwRenderTarget> rt, size_t width, size_t height) {
|
||||||
|
return getRenderTarget(rt, width, height, PixelDataFormat::RGBA,
|
||||||
|
PixelDataType::UBYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Environment : public ::testing::Environment {
|
class Environment : public ::testing::Environment {
|
||||||
public:
|
public:
|
||||||
virtual void SetUp() override {
|
virtual void SetUp() override {
|
||||||
|
|||||||
@@ -67,6 +67,17 @@ protected:
|
|||||||
filament::backend::Driver& getDriver() { return *driver; }
|
filament::backend::Driver& getDriver() { return *driver; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void writeImage(utils::FixedCapacityVector<uint8_t> img, size_t w, size_t h,
|
||||||
|
utils::CString const& fname);
|
||||||
|
utils::FixedCapacityVector<uint8_t> getRenderTarget(
|
||||||
|
filament::backend::Handle<filament::backend::HwRenderTarget> rt, size_t width,
|
||||||
|
size_t height, filament::backend::PixelDataFormat format,
|
||||||
|
filament::backend::PixelDataType dataType);
|
||||||
|
uint32_t computeImageHash(utils::FixedCapacityVector<uint8_t> const& img);
|
||||||
|
|
||||||
|
utils::FixedCapacityVector<uint8_t> getRenderTargetRGB(
|
||||||
|
filament::backend::Handle<filament::backend::HwRenderTarget> rt, size_t width,
|
||||||
|
size_t height);
|
||||||
|
|
||||||
filament::backend::Driver* driver = nullptr;
|
filament::backend::Driver* driver = nullptr;
|
||||||
filament::backend::CommandBufferQueue commandBufferQueue;
|
filament::backend::CommandBufferQueue commandBufferQueue;
|
||||||
|
|||||||
@@ -60,36 +60,6 @@ struct MaterialParams {
|
|||||||
float4 scale;
|
float4 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScreenshotParams {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
const char* filename;
|
|
||||||
uint32_t pixelHashResult;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef IOS
|
|
||||||
static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt, ScreenshotParams* params) {}
|
|
||||||
#else
|
|
||||||
static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt, ScreenshotParams* params) {
|
|
||||||
using namespace image;
|
|
||||||
const size_t size = params->width * params->height * 4;
|
|
||||||
void* buffer = calloc(1, size);
|
|
||||||
auto cb = [](void* buffer, size_t size, void* user) {
|
|
||||||
ScreenshotParams* params = (ScreenshotParams*) user;
|
|
||||||
int w = params->width, h = params->height;
|
|
||||||
const uint32_t* texels = (uint32_t*) buffer;
|
|
||||||
params->pixelHashResult = utils::hash::murmur3(texels, size / 4, 0);
|
|
||||||
LinearImage image(w, h, 4);
|
|
||||||
image = toLinearWithAlpha<uint8_t>(w, h, w * 4, (uint8_t*) buffer);
|
|
||||||
std::ofstream pngstrm(params->filename, std::ios::binary | std::ios::trunc);
|
|
||||||
ImageEncoder::encode(pngstrm, ImageEncoder::Format::PNG, image, "", params->filename);
|
|
||||||
};
|
|
||||||
PixelBufferDescriptor pb(buffer, size, PixelDataFormat::RGBA, PixelDataType::UBYTE, cb,
|
|
||||||
(void*) params);
|
|
||||||
dapi.readPixels(rt, 0, 0, params->width, params->height, std::move(pb));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void uploadUniforms(DriverApi& dapi, Handle<HwBufferObject> ubh, MaterialParams params) {
|
static void uploadUniforms(DriverApi& dapi, Handle<HwBufferObject> ubh, MaterialParams params) {
|
||||||
MaterialParams* tmp = new MaterialParams(params);
|
MaterialParams* tmp = new MaterialParams(params);
|
||||||
auto cb = [](void* buffer, size_t size, void* user) {
|
auto cb = [](void* buffer, size_t size, void* user) {
|
||||||
@@ -243,21 +213,12 @@ TEST_F(BackendTest, ColorMagnify) {
|
|||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
|
||||||
// Grab a screenshot.
|
// Grab a screenshot.
|
||||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "ColorMagnify.png" };
|
|
||||||
api.beginFrame(0, 0, 0);
|
api.beginFrame(0, 0, 0);
|
||||||
dumpScreenshot(api, dstRenderTargets[0], ¶ms);
|
constexpr uint32_t expected = 0x410bdd31;
|
||||||
api.commit(swapChain);
|
readPixelsAndAssertHash("ColorMagnify", kDstTexWidth, kDstTexHeight, dstRenderTargets[0],
|
||||||
|
expected, true);
|
||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
flushAndWait();
|
||||||
// Wait for the ReadPixels result to come back.
|
|
||||||
api.finish();
|
|
||||||
executeCommands();
|
|
||||||
getDriver().purge();
|
|
||||||
|
|
||||||
// Check if the image matches perfectly to our golden run.
|
|
||||||
const uint32_t expected = 0x410bdd31;
|
|
||||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
|
||||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyTexture(srcTexture);
|
api.destroyTexture(srcTexture);
|
||||||
@@ -315,17 +276,15 @@ TEST_F(BackendTest, ColorMinify) {
|
|||||||
SamplerMagFilter::LINEAR);
|
SamplerMagFilter::LINEAR);
|
||||||
|
|
||||||
// Grab a screenshot.
|
// Grab a screenshot.
|
||||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "ColorMinify.png" };
|
api.beginFrame(0, 0, 0);
|
||||||
dumpScreenshot(api, dstRenderTargets[0], ¶ms);
|
constexpr uint32_t expected = 0xf3d9c53f;
|
||||||
|
readPixelsAndAssertHash("ColorMinify", kDstTexWidth, kDstTexHeight, dstRenderTargets[0],
|
||||||
|
expected, true);
|
||||||
|
|
||||||
// Wait for the ReadPixels result to come back.
|
api.commit(swapChain);
|
||||||
|
api.endFrame(0);
|
||||||
flushAndWait();
|
flushAndWait();
|
||||||
|
|
||||||
// Check if the image matches perfectly to our golden run.
|
|
||||||
const uint32_t expected = 0xf3d9c53f;
|
|
||||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
|
||||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyTexture(srcTexture);
|
api.destroyTexture(srcTexture);
|
||||||
api.destroyTexture(dstTexture);
|
api.destroyTexture(dstTexture);
|
||||||
@@ -416,17 +375,13 @@ TEST_F(BackendTest, ColorResolve) {
|
|||||||
SamplerMagFilter::NEAREST);
|
SamplerMagFilter::NEAREST);
|
||||||
|
|
||||||
// Grab a screenshot.
|
// Grab a screenshot.
|
||||||
ScreenshotParams sparams{ kDstTexWidth, kDstTexHeight, "ColorResolve.png" };
|
api.beginFrame(0, 0, 0);
|
||||||
dumpScreenshot(api, dstRenderTarget, &sparams);
|
constexpr uint32_t expected = 0xebfac2ef;
|
||||||
|
readPixelsAndAssertHash("ColorResolve", kDstTexWidth, kDstTexHeight, dstRenderTarget,
|
||||||
// Wait for the ReadPixels result to come back.
|
expected, true);
|
||||||
|
api.endFrame(0);
|
||||||
flushAndWait();
|
flushAndWait();
|
||||||
|
|
||||||
// Check if the image matches perfectly to our golden run.
|
|
||||||
const uint32_t expected = 0xebfac2ef;
|
|
||||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", sparams.pixelHashResult, expected);
|
|
||||||
EXPECT_TRUE(sparams.pixelHashResult == expected);
|
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyBufferObject(ubuffer);
|
api.destroyBufferObject(ubuffer);
|
||||||
api.destroyProgram(program);
|
api.destroyProgram(program);
|
||||||
@@ -489,21 +444,12 @@ TEST_F(BackendTest, Blit2DTextureArray) {
|
|||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
|
||||||
// Grab a screenshot.
|
// Grab a screenshot.
|
||||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "Blit2DTextureArray.png" };
|
|
||||||
api.beginFrame(0, 0, 0);
|
api.beginFrame(0, 0, 0);
|
||||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
constexpr uint32_t expected = 0x8de7d55b;
|
||||||
api.commit(swapChain);
|
readPixelsAndAssertHash("Blit2DTextureArray", kDstTexWidth, kDstTexHeight, dstRenderTarget,
|
||||||
|
expected, true);
|
||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
flushAndWait();
|
||||||
// Wait for the ReadPixels result to come back.
|
|
||||||
api.finish();
|
|
||||||
executeCommands();
|
|
||||||
getDriver().purge();
|
|
||||||
|
|
||||||
// Check if the image matches perfectly to our golden run.
|
|
||||||
const uint32_t expected = 0x8de7d55b;
|
|
||||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
|
||||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyTexture(srcTexture);
|
api.destroyTexture(srcTexture);
|
||||||
@@ -578,28 +524,17 @@ TEST_F(BackendTest, BlitRegion) {
|
|||||||
api.commit(swapChain);
|
api.commit(swapChain);
|
||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
|
||||||
// Grab a screenshot.
|
|
||||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "BlitRegion.png" };
|
|
||||||
api.beginFrame(0, 0, 0);
|
|
||||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
|
||||||
api.commit(swapChain);
|
|
||||||
api.endFrame(0);
|
|
||||||
|
|
||||||
// Wait for the ReadPixels result to come back.
|
|
||||||
api.finish();
|
|
||||||
executeCommands();
|
|
||||||
getDriver().purge();
|
|
||||||
|
|
||||||
// Check if the image matches perfectly to our golden run.
|
// Check if the image matches perfectly to our golden run.
|
||||||
//
|
|
||||||
// TODO: for some reason, this test has very, very slight (as in one pixel) differences between
|
// TODO: for some reason, this test has very, very slight (as in one pixel) differences between
|
||||||
// OpenGL and Metal. So disable golden checking for now.
|
// OpenGL and Metal. So disable golden checking for now.
|
||||||
// Use the compare tool from ImageMagick to see visual differences:
|
// Use the compare tool from ImageMagick to see visual differences:
|
||||||
// compare -verbose -metric mae BlitRegion_Metal.png BlitRegion_OpenGL.png difference.png
|
// compare -verbose -metric mae BlitRegion_Metal.png BlitRegion_OpenGL.png difference.png
|
||||||
//
|
// api.beginFrame(0, 0, 0);
|
||||||
// const uint32_t expected = 0x74fa34ed;
|
// constexpr uint32_t expected = 0x74fa34ed;
|
||||||
// printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
// readPixelsAndAssertHash("BlitRegion", kDstTexWidth, kDstTexHeight, dstRenderTarget,
|
||||||
// EXPECT_TRUE(params.pixelHashResult == expected);
|
// expected, true);
|
||||||
|
// api.endFrame(0);
|
||||||
|
// flushAndWait();
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyTexture(srcTexture);
|
api.destroyTexture(srcTexture);
|
||||||
@@ -655,23 +590,22 @@ TEST_F(BackendTest, BlitRegionToSwapChain) {
|
|||||||
.height = kDstTexHeight - 10,
|
.height = kDstTexHeight - 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.beginFrame(0, 0, 0);
|
|
||||||
|
|
||||||
api.blitDEPRECATED(TargetBufferFlags::COLOR0, dstRenderTarget,
|
api.blitDEPRECATED(TargetBufferFlags::COLOR0, dstRenderTarget,
|
||||||
dstRect, srcRenderTargets[srcLevel],
|
dstRect, srcRenderTargets[srcLevel],
|
||||||
srcRect, SamplerMagFilter::LINEAR);
|
srcRect, SamplerMagFilter::LINEAR);
|
||||||
|
|
||||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain.png" };
|
// Push through an empty frame to allow the texture to upload and the blit to execute.
|
||||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
api.beginFrame(0, 0, 0);
|
||||||
|
|
||||||
api.commit(swapChain);
|
api.commit(swapChain);
|
||||||
|
|
||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
|
|
||||||
// Wait for the ReadPixels result to come back.
|
// Grab a screenshot.
|
||||||
api.finish();
|
api.beginFrame(0, 0, 0);
|
||||||
executeCommands();
|
constexpr uint32_t expected = 0xebfac2ef;
|
||||||
getDriver().purge();
|
readPixelsAndAssertHash("BlitRegionToSwapChain", kDstTexWidth, kDstTexHeight, dstRenderTarget,
|
||||||
|
expected, true);
|
||||||
|
api.endFrame(0);
|
||||||
|
flushAndWait();
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
api.destroyTexture(srcTexture);
|
api.destroyTexture(srcTexture);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "BackendTest.h"
|
#include "BackendTest.h"
|
||||||
|
|
||||||
|
#include "BackendTestUtils.h"
|
||||||
#include "ShaderGenerator.h"
|
#include "ShaderGenerator.h"
|
||||||
#include "TrianglePrimitive.h"
|
#include "TrianglePrimitive.h"
|
||||||
|
|
||||||
@@ -64,8 +65,6 @@ void main() {
|
|||||||
fragColor = textureLod(test_tex, uv, params.sourceLevel);
|
fragColor = textureLod(test_tex, uv, params.sourceLevel);
|
||||||
})";
|
})";
|
||||||
|
|
||||||
static uint32_t sPixelHashResult = 0;
|
|
||||||
|
|
||||||
// Selecting a NPOT texture size seems to exacerbate the bug seen with Intel GPU's.
|
// Selecting a NPOT texture size seems to exacerbate the bug seen with Intel GPU's.
|
||||||
// Note that Filament uses a higher precision format (R11F_G11F_B10F) but this does not seem
|
// Note that Filament uses a higher precision format (R11F_G11F_B10F) but this does not seem
|
||||||
// necessary to trigger the bug.
|
// necessary to trigger the bug.
|
||||||
@@ -99,30 +98,13 @@ static void uploadUniforms(DriverApi& dapi, Handle<HwBufferObject> ubh, Material
|
|||||||
dapi.updateBufferObject(ubh, std::move(bd), 0);
|
dapi.updateBufferObject(ubh, std::move(bd), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dumpScreenshot(DriverApi& dapi, Handle<HwRenderTarget> rt) {
|
|
||||||
const size_t size = kTexWidth * kTexHeight * 4;
|
|
||||||
void* buffer = calloc(1, size);
|
|
||||||
auto cb = [](void* buffer, size_t size, void* user) {
|
|
||||||
int w = kTexWidth, h = kTexHeight;
|
|
||||||
const uint32_t* texels = (uint32_t*) buffer;
|
|
||||||
sPixelHashResult = utils::hash::murmur3(texels, size / 4, 0);
|
|
||||||
#ifndef IOS
|
|
||||||
LinearImage image(w, h, 4);
|
|
||||||
image = toLinearWithAlpha<uint8_t>(w, h, w * 4, (uint8_t*) buffer);
|
|
||||||
std::ofstream pngstrm("feedback.png", std::ios::binary | std::ios::trunc);
|
|
||||||
ImageEncoder::encode(pngstrm, ImageEncoder::Format::PNG, image, "", "feedback.png");
|
|
||||||
#endif
|
|
||||||
free(buffer);
|
|
||||||
};
|
|
||||||
PixelBufferDescriptor pb(buffer, size, PixelDataFormat::RGBA, PixelDataType::UBYTE, cb);
|
|
||||||
dapi.readPixels(rt, 0, 0, kTexWidth, kTexHeight, std::move(pb));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This test needs work to get Metal and OpenGL to agree on results.
|
// TODO: This test needs work to get Metal and OpenGL to agree on results.
|
||||||
// The problems are caused by both uploading and rendering into the same texture, since the OpenGL
|
// The problems are caused by both uploading and rendering into the same texture, since the OpenGL
|
||||||
// backend's readPixels does not work correctly with textures that have image data uploaded.
|
// backend's readPixels does not work correctly with textures that have image data uploaded.
|
||||||
TEST_F(BackendTest, FeedbackLoops) {
|
TEST_F(BackendTest, FeedbackLoops) {
|
||||||
auto& api = getDriverApi();
|
auto& api = getDriverApi();
|
||||||
|
auto& driver = getDriver();
|
||||||
|
uint32_t pixelHashResult = 0;
|
||||||
|
|
||||||
// The test is executed within this block scope to force destructors to run before
|
// The test is executed within this block scope to force destructors to run before
|
||||||
// executeCommands().
|
// executeCommands().
|
||||||
@@ -147,7 +129,7 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
program = api.createProgram(std::move(prog));
|
program = api.createProgram(std::move(prog));
|
||||||
}
|
}
|
||||||
|
|
||||||
TrianglePrimitive const triangle(getDriverApi());
|
TrianglePrimitive const triangle(api);
|
||||||
|
|
||||||
// Create a texture.
|
// Create a texture.
|
||||||
auto usage = TextureUsage::COLOR_ATTACHMENT | TextureUsage::SAMPLEABLE;
|
auto usage = TextureUsage::COLOR_ATTACHMENT | TextureUsage::SAMPLEABLE;
|
||||||
@@ -211,8 +193,8 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
const uint32_t sourceLevel = targetLevel - 1;
|
const uint32_t sourceLevel = targetLevel - 1;
|
||||||
params.viewport.width = kTexWidth >> targetLevel;
|
params.viewport.width = kTexWidth >> targetLevel;
|
||||||
params.viewport.height = kTexHeight >> targetLevel;
|
params.viewport.height = kTexHeight >> targetLevel;
|
||||||
getDriverApi().setMinMaxLevels(texture, sourceLevel, sourceLevel);
|
api.setMinMaxLevels(texture, sourceLevel, sourceLevel);
|
||||||
uploadUniforms(getDriverApi(), ubuffer, {
|
uploadUniforms(api, ubuffer, {
|
||||||
.fbWidth = float(params.viewport.width),
|
.fbWidth = float(params.viewport.width),
|
||||||
.fbHeight = float(params.viewport.height),
|
.fbHeight = float(params.viewport.height),
|
||||||
.sourceLevel = float(sourceLevel),
|
.sourceLevel = float(sourceLevel),
|
||||||
@@ -230,8 +212,8 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
const uint32_t sourceLevel = targetLevel + 1;
|
const uint32_t sourceLevel = targetLevel + 1;
|
||||||
params.viewport.width = kTexWidth >> targetLevel;
|
params.viewport.width = kTexWidth >> targetLevel;
|
||||||
params.viewport.height = kTexHeight >> targetLevel;
|
params.viewport.height = kTexHeight >> targetLevel;
|
||||||
getDriverApi().setMinMaxLevels(texture, sourceLevel, sourceLevel);
|
api.setMinMaxLevels(texture, sourceLevel, sourceLevel);
|
||||||
uploadUniforms(getDriverApi(), ubuffer, {
|
uploadUniforms(api, ubuffer, {
|
||||||
.fbWidth = float(params.viewport.width),
|
.fbWidth = float(params.viewport.width),
|
||||||
.fbHeight = float(params.viewport.height),
|
.fbHeight = float(params.viewport.height),
|
||||||
.sourceLevel = float(sourceLevel),
|
.sourceLevel = float(sourceLevel),
|
||||||
@@ -241,14 +223,16 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
api.endRenderPass();
|
api.endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
getDriverApi().setMinMaxLevels(texture, 0, 0x7f);
|
api.setMinMaxLevels(texture, 0, 0x7f);
|
||||||
|
|
||||||
// Read back the render target corresponding to the base level.
|
// Read back the render target corresponding to the base level.
|
||||||
//
|
//
|
||||||
// NOTE: Calling glReadPixels on any miplevel other than the base level
|
// NOTE: Calling glReadPixels on any miplevel other than the base level
|
||||||
// seems to be un-reliable on some GPU's.
|
// seems to be un-reliable on some GPU's.
|
||||||
if (frame == kNumFrames - 1) {
|
if (frame == kNumFrames - 1) {
|
||||||
dumpScreenshot(api, renderTargets[0]);
|
constexpr uint32_t expected = 0x70695aa1;
|
||||||
|
readPixelsAndAssertHash("feedback", kTexWidth, kTexHeight, renderTargets[0],
|
||||||
|
expected, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
api.flush();
|
api.flush();
|
||||||
@@ -256,7 +240,7 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
api.endFrame(0);
|
api.endFrame(0);
|
||||||
api.finish();
|
api.finish();
|
||||||
executeCommands();
|
executeCommands();
|
||||||
getDriver().purge();
|
driver.purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
api.destroyProgram(program);
|
api.destroyProgram(program);
|
||||||
@@ -264,10 +248,6 @@ TEST_F(BackendTest, FeedbackLoops) {
|
|||||||
api.destroyTexture(texture);
|
api.destroyTexture(texture);
|
||||||
for (auto rt : renderTargets) api.destroyRenderTarget(rt);
|
for (auto rt : renderTargets) api.destroyRenderTarget(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t expected = 0x70695aa1;
|
|
||||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", sPixelHashResult, expected);
|
|
||||||
EXPECT_TRUE(sPixelHashResult == expected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
|||||||
Reference in New Issue
Block a user