diff --git a/filament/backend/src/vulkan/VulkanReadPixels.cpp b/filament/backend/src/vulkan/VulkanReadPixels.cpp index 2fc7ee2e09..79696eb9c8 100644 --- a/filament/backend/src/vulkan/VulkanReadPixels.cpp +++ b/filament/backend/src/vulkan/VulkanReadPixels.cpp @@ -303,7 +303,7 @@ void VulkanReadPixels::run(VulkanRenderTarget* srcTarget, uint32_t const x, uint VkResult status = vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX); // Fence hasn't been reached. Try waiting again. if (status != VK_SUCCESS) { - utils::slog.e << "Failed to wait for readPixels fence" << utils::io::endl; + utils::slog.e << "Failed to wait for readPixels fence=" << status << utils::io::endl; return; } diff --git a/filament/backend/test/ShaderGenerator.cpp b/filament/backend/test/ShaderGenerator.cpp index 7d0ad716e1..34cee77516 100644 --- a/filament/backend/test/ShaderGenerator.cpp +++ b/filament/backend/test/ShaderGenerator.cpp @@ -22,11 +22,14 @@ #include #include +#include + #include "../src/GLSLPostProcessor.h" #include "builtinResource.h" #include +#include #include #include @@ -36,6 +39,7 @@ namespace test { using namespace glslang; using namespace spirv_cross; +using namespace spvtools; using namespace filament::backend; @@ -128,6 +132,8 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader( bool ok = tShader.parse(&DefaultTBuiltInResource, version, false, msg); + utils::slog.e <<"-----------" << shaderCString << utils::io::endl; + if (!ok) { std::cerr << "ERROR: Unable to parse " << (stage == ShaderStage::VERTEX ? "vertex" : "fragment") << " shader:" << std::endl; @@ -146,6 +152,13 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader( GlslangToSpv(*program.getIntermediate(language), spirv); + SpirvTools const tools(SPV_ENV_UNIVERSAL_1_3); + std::string disassembly; + bool rr = tools.Disassemble(spirv, &disassembly); + + utils::slog.e <<"dissambly=" << rr << "\n" << + disassembly << utils::io::endl; + std::string result; assert_invariant(backend == Backend::OPENGL || diff --git a/filament/backend/test/test_LoadImage.cpp b/filament/backend/test/test_LoadImage.cpp index 2af57eb719..6abfa1f51c 100644 --- a/filament/backend/test/test_LoadImage.cpp +++ b/filament/backend/test/test_LoadImage.cpp @@ -23,11 +23,22 @@ #include "private/filament/SamplerInterfaceBlock.h" #include "private/backend/SamplerGroup.h" +#include +#include + #include #include #include +#ifndef IOS +#include +#include + +using namespace image; +#endif + + using namespace filament; using namespace filament::backend; @@ -56,7 +67,7 @@ layout(location = 0) out vec4 fragColor; // Filament's Vulkan backend requires a descriptor set index of 1 for all samplers. // This parameter is ignored for other backends. -layout(location = 0, set = 1) uniform {samplerType} test_tex; +layout(binding = 0, set = 1) uniform {samplerType} test_tex; void main() { vec2 fbsize = vec2(512); @@ -109,6 +120,49 @@ void main() { )"); } +static void readScreenshot(DriverApi& dapi, Handle rt, size_t const readWidth, + size_t const readHeight, std::function output) { + size_t const size = readWidth * readHeight * 4; + void* buffer = calloc(1, size); + struct ReadPixelUserData { + std::function onRead; + }; + ReadPixelUserData* userdata = new ReadPixelUserData{output}; + auto cb = [](void* buffer, size_t size, void* user) { + ReadPixelUserData* data = (ReadPixelUserData*) user; + data->onRead(buffer); + free(buffer); + delete data; + }; + PixelBufferDescriptor pb(buffer, size, PixelDataFormat::RGBA, PixelDataType::UBYTE, cb, + userdata); + dapi.readPixels(rt, 0, 0, readWidth, readHeight, std::move(pb)); +} + +static void dumpScreenshot(DriverApi& dapi, Handle rt, size_t const readWidth, + size_t const readHeight, test::Backend backend, std::string fname = "") { + size_t const size = readWidth * readHeight * 4; + if (fname.empty()) { + std::string backendStr = "gl"; + if (backend == test::Backend::METAL) { + backendStr = "mtl"; + } else if (backend == test::Backend::VULKAN) { + backendStr = "vk"; + } + fname = "feedback_" + backendStr + "_" + ".png"; + } + utils::slog.e << "writing: " << fname << utils::io::endl; + readScreenshot(dapi, rt, readWidth, readHeight, [w = readWidth, h = readHeight, size, fname](void* buffer) { + uint32_t const* texels = (uint32_t*) buffer; + auto hashResutl = utils::hash::murmur3(texels, size / 4, 0); +#ifndef IOS + LinearImage image(w, h, 4); + image = toLinearWithAlpha(w, h, w * 4, (uint8_t*) buffer); + std::ofstream pngstrm(fname.c_str(), std::ios::binary | std::ios::trunc); + ImageEncoder::encode(pngstrm, ImageEncoder::Format::PNG, image, "", fname.c_str()); +#endif + }); +} namespace test { @@ -246,21 +300,22 @@ TEST_F(BackendTest, UpdateImage2D) { std::vector testCases; + // Test basic upload. testCases.emplace_back("RGBA, UBYTE -> RGBA8", PixelDataFormat::RGBA, PixelDataType::UBYTE, TextureFormat::RGBA8); // Test format conversion. // TODO: Vulkan crashes with `Texture at colorAttachment[0] has usage (0x01) which doesn't specify MTLTextureUsageRenderTarget (0x04)' testCases.emplace_back("RGBA, FLOAT -> RGBA16F", PixelDataFormat::RGBA, PixelDataType::FLOAT, TextureFormat::RGBA16F); - + /* // Test texture formats not all backends support natively. // TODO: Vulkan crashes with "VK_FORMAT_R32G32B32_SFLOAT is not supported" testCases.emplace_back("RGB, FLOAT -> RGB32F", PixelDataFormat::RGB, PixelDataType::FLOAT, TextureFormat::RGB32F); testCases.emplace_back("RGB, FLOAT -> RGB16F", PixelDataFormat::RGB, PixelDataType::FLOAT, TextureFormat::RGB16F); - // Test packed format uploads. + // packed Test format uploads. // TODO: Vulkan crashes with "Texture at colorAttachment[0] has usage (0x01) which doesn't specify MTLTextureUsageRenderTarget (0x04)" - testCases.emplace_back("RGBA, UINT_2_10_10_10_REV -> RGB10_A2", PixelDataFormat::RGBA, PixelDataType::UINT_2_10_10_10_REV, TextureFormat::RGB10_A2); + testCases.emplace_back("RGBA, UINT_2_10_10_10_REV -> RGB10_A2", PixelDataFormat::RGBA, PixelDataType::UINT_2_10_10_10_REV, TextureFormat::RGB10_A2);gitgg testCases.emplace_back("RGB, UINT_10F_11F_11F_REV -> R11F_G11F_B10F", PixelDataFormat::RGB, PixelDataType::UINT_10F_11F_11F_REV, TextureFormat::R11F_G11F_B10F); testCases.emplace_back("RGB, HALF -> R11F_G11F_B10F", PixelDataFormat::RGB, PixelDataType::HALF, TextureFormat::R11F_G11F_B10F); @@ -281,8 +336,9 @@ TEST_F(BackendTest, UpdateImage2D) { // TODO: Vulkan crashes with "Offsets not yet supported" testCases.emplace_back("RGBA, UBYTE -> RGBA8 (subregions)", PixelDataFormat::RGBA, PixelDataType::UBYTE, TextureFormat::RGBA8, 0u, true); testCases.emplace_back("RGBA, FLOAT -> RGBA16F (subregions)", PixelDataFormat::RGBA, PixelDataType::FLOAT, TextureFormat::RGBA16F, 0u, true); - testCases.emplace_back("RGBA, UBYTE -> RGBA8 (subregions, buffer padding)", PixelDataFormat::RGBA, PixelDataType::UBYTE, TextureFormat::RGBA8, 64u, true); + testCases.emplace_back("RGBA, UBYTE -> RGBA8 (subregions, buffer padding)", PixelDataFormat::RGBA, PixelDataType::UBYTE, TextureFormat::RGBA8, 64u, true); testCases.emplace_back("RGB, FLOAT -> RGB32F (subregions, buffer padding)", PixelDataFormat::RGB, PixelDataType::FLOAT, TextureFormat::RGB32F, 64u, true); + */ auto& api = getDriverApi(); @@ -305,6 +361,7 @@ TEST_F(BackendTest, UpdateImage2D) { std::string const fragment = stringReplace("{samplerType}", getSamplerTypeName(t.textureFormat), fragmentTemplate); + utils::slog.e <<"sampler=" << fragment << utils::io::endl; ShaderGenerator shaderGen(vertex, fragment, sBackend, sIsMobilePlatform, &sib); Program prog = shaderGen.getProgram(api); Program::Sampler psamplers[] = { utils::CString("test_tex"), 0 }; @@ -348,6 +405,8 @@ TEST_F(BackendTest, UpdateImage2D) { api.commit(swapChain); api.endFrame(0); +// dumpScreenshot(api, defaultRenderTarget, 512, 512, test::Backend::VULKAN, t.name); + api.destroyProgram(program); api.destroySwapChain(swapChain); api.destroyRenderTarget(defaultRenderTarget);