[Impeller] Add debug ToString methods to render targets. (flutter/engine#41221)

Also fixes and issue where SPrintF would only consider strings 64 bytes or smaller.
This commit is contained in:
Chinmay Garde 2023-04-17 14:57:18 -07:00 committed by GitHub
parent b8b3e21214
commit ea8977d178
11 changed files with 202 additions and 7 deletions

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "flutter/testing/testing.h"
#include "impeller/base/strings.h"
#include "impeller/base/thread.h"
namespace impeller {
@ -68,5 +69,12 @@ TEST(ThreadTest, CanCreateRWMutexLock) {
// f.mtx.UnlockReader(); <--- Static analysis error.
}
TEST(StringsTest, CanSPrintF) {
ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
ASSERT_EQ(SPrintF(""), "");
ASSERT_EQ(SPrintF("Hello"), "Hello");
ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
}
} // namespace testing
} // namespace impeller

View File

@ -10,12 +10,21 @@ namespace impeller {
IMPELLER_PRINTF_FORMAT(1, 2)
std::string SPrintF(const char* format, ...) {
std::string ret_val;
va_list list;
va_list list2;
va_start(list, format);
char buffer[64] = {0};
::vsnprintf(buffer, sizeof(buffer), format, list);
va_copy(list2, list);
if (auto string_length = ::vsnprintf(nullptr, 0, format, list);
string_length >= 0) {
auto buffer = reinterpret_cast<char*>(::malloc(string_length + 1));
::vsnprintf(buffer, string_length + 1, format, list2);
ret_val = std::string{buffer, static_cast<size_t>(string_length)};
::free(buffer);
}
va_end(list2);
va_end(list);
return buffer;
return ret_val;
}
bool HasPrefix(const std::string& string, const std::string& prefix) {

View File

@ -101,4 +101,44 @@ std::string TextureUsageMaskToString(TextureUsageMask mask) {
return stream.str();
}
std::string AttachmentToString(const Attachment& attachment) {
std::stringstream stream;
if (attachment.texture) {
stream << "Texture=("
<< TextureDescriptorToString(
attachment.texture->GetTextureDescriptor())
<< "),";
}
if (attachment.resolve_texture) {
stream << "ResolveTexture=("
<< TextureDescriptorToString(
attachment.resolve_texture->GetTextureDescriptor())
<< "),";
}
stream << "LoadAction=" << LoadActionToString(attachment.load_action) << ",";
stream << "StoreAction=" << StoreActionToString(attachment.store_action);
return stream.str();
}
std::string ColorAttachmentToString(const ColorAttachment& color) {
std::stringstream stream;
stream << AttachmentToString(color) << ",";
stream << "ClearColor=(" << ColorToString(color.clear_color) << ")";
return stream.str();
}
std::string DepthAttachmentToString(const DepthAttachment& depth) {
std::stringstream stream;
stream << AttachmentToString(depth) << ",";
stream << "ClearDepth=" << SPrintF("%.2f", depth.clear_depth);
return stream.str();
}
std::string StencilAttachmentToString(const StencilAttachment& stencil) {
std::stringstream stream;
stream << AttachmentToString(stencil) << ",";
stream << "ClearStencil=" << stencil.clear_stencil;
return stream.str();
}
} // namespace impeller

View File

@ -110,6 +110,42 @@ enum class PixelFormat {
kD32FloatS8UInt,
};
constexpr const char* PixelFormatToString(PixelFormat format) {
switch (format) {
case PixelFormat::kUnknown:
return "Unknown";
case PixelFormat::kA8UNormInt:
return "A8UNormInt";
case PixelFormat::kR8UNormInt:
return "R8UNormInt";
case PixelFormat::kR8G8UNormInt:
return "R8G8UNormInt";
case PixelFormat::kR8G8B8A8UNormInt:
return "R8G8B8A8UNormInt";
case PixelFormat::kR8G8B8A8UNormIntSRGB:
return "R8G8B8A8UNormIntSRGB";
case PixelFormat::kB8G8R8A8UNormInt:
return "B8G8R8A8UNormInt";
case PixelFormat::kB8G8R8A8UNormIntSRGB:
return "B8G8R8A8UNormIntSRGB";
case PixelFormat::kR32G32B32A32Float:
return "R32G32B32A32Float";
case PixelFormat::kR16G16B16A16Float:
return "R16G16B16A16Float";
case PixelFormat::kB10G10R10XR:
return "B10G10R10XR";
case PixelFormat::kB10G10R10XRSRGB:
return "B10G10R10XRSRGB";
case PixelFormat::kB10G10R10A10XR:
return "B10G10R10A10XR";
case PixelFormat::kS8UInt:
return "S8UInt";
case PixelFormat::kD32FloatS8UInt:
return "D32FloatS8UInt";
}
FML_UNREACHABLE();
}
enum class BlendFactor {
kZero,
kOne,
@ -147,6 +183,30 @@ enum class StoreAction {
kStoreAndMultisampleResolve,
};
constexpr const char* LoadActionToString(LoadAction action) {
switch (action) {
case LoadAction::kDontCare:
return "DontCare";
case LoadAction::kLoad:
return "Load";
case LoadAction::kClear:
return "Clear";
}
}
constexpr const char* StoreActionToString(StoreAction action) {
switch (action) {
case StoreAction::kDontCare:
return "DontCare";
case StoreAction::kStore:
return "Store";
case StoreAction::kMultisampleResolve:
return "MultisampleResolve";
case StoreAction::kStoreAndMultisampleResolve:
return "StoreAndMultisampleResolve";
}
}
constexpr bool CanClearAttachment(LoadAction action) {
switch (action) {
case LoadAction::kLoad:
@ -530,6 +590,14 @@ struct StencilAttachment : public Attachment {
uint32_t clear_stencil = 0;
};
std::string AttachmentToString(const Attachment& attachment);
std::string ColorAttachmentToString(const ColorAttachment& color);
std::string DepthAttachmentToString(const DepthAttachment& depth);
std::string StencilAttachmentToString(const StencilAttachment& stencil);
} // namespace impeller
namespace std {

View File

@ -4,8 +4,20 @@
#include "impeller/core/texture_descriptor.h"
#include <sstream>
namespace impeller {
//
std::string TextureDescriptorToString(const TextureDescriptor& desc) {
std::stringstream stream;
stream << "StorageMode=" << StorageModeToString(desc.storage_mode) << ",";
stream << "Type=" << TextureTypeToString(desc.type) << ",";
stream << "Format=" << PixelFormatToString(desc.format) << ",";
stream << "Size=" << desc.size << ",";
stream << "MipCount=" << desc.mip_count << ",";
stream << "SampleCount=" << static_cast<size_t>(desc.sample_count) << ",";
stream << "Compression=" << CompressionTypeToString(desc.compression_type);
return stream.str();
}
} // namespace impeller

View File

@ -21,6 +21,17 @@ enum class CompressionType {
kLossless,
kLossy,
};
constexpr const char* CompressionTypeToString(CompressionType type) {
switch (type) {
case CompressionType::kLossless:
return "Lossless";
case CompressionType::kLossy:
return "Lossy";
}
FML_UNREACHABLE();
}
//------------------------------------------------------------------------------
/// @brief A lightweight object that describes the attributes of a texture
/// that can then used an allocator to create that texture.
@ -63,4 +74,6 @@ struct TextureDescriptor {
}
};
std::string TextureDescriptorToString(const TextureDescriptor& desc);
} // namespace impeller

View File

@ -42,7 +42,10 @@ impeller_component("geometry") {
"vector.h",
]
deps = [ "//flutter/fml" ]
deps = [
"../base",
"//flutter/fml",
]
}
impeller_component("geometry_asserts") {

View File

@ -8,6 +8,7 @@
#include <cmath>
#include <sstream>
#include "impeller/base/strings.h"
#include "impeller/geometry/constants.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/vector.h"
@ -360,4 +361,13 @@ Color Color::BlendColor(const Color& src,
}
}
std::string ColorToString(const Color& color) {
return SPrintF("R=%.1f,G=%.1f,B=%.1f,A=%.1f", //
color.red, //
color.green, //
color.blue, //
color.alpha //
);
}
} // namespace impeller

View File

@ -797,6 +797,8 @@ struct Color {
constexpr bool IsOpaque() const { return alpha == 1.0f; }
};
std::string ColorToString(const Color& color);
/**
* Represents a color by its constituent hue, saturation, brightness and alpha
*/

View File

@ -4,6 +4,8 @@
#include "impeller/renderer/render_target.h"
#include <sstream>
#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/core/allocator.h"
@ -59,12 +61,20 @@ bool RenderTarget::IsValid() const {
if (texture_type != attachment.texture->GetTextureDescriptor().type) {
passes_type_validation = false;
VALIDATION_LOG << "Render target has incompatible texture types: "
<< TextureTypeToString(texture_type.value()) << " != "
<< TextureTypeToString(
attachment.texture->GetTextureDescriptor().type)
<< " on target " << ToString();
return false;
}
if (sample_count !=
attachment.texture->GetTextureDescriptor().sample_count) {
passes_type_validation = false;
VALIDATION_LOG << "Render target (" << ToString()
<< ") has incompatible sample counts.";
return false;
}
@ -72,8 +82,6 @@ bool RenderTarget::IsValid() const {
};
IterateAllAttachments(iterator);
if (!passes_type_validation) {
VALIDATION_LOG << "Render target texture types are not of the same type "
"and sample count.";
return false;
}
}
@ -370,4 +378,24 @@ size_t RenderTarget::GetTotalAttachmentCount() const {
return count;
}
std::string RenderTarget::ToString() const {
std::stringstream stream;
for (const auto& [index, color] : colors_) {
stream << SPrintF("Color[%zu]=(%s)", index,
ColorAttachmentToString(color).c_str());
}
if (depth_) {
stream << ",";
stream << SPrintF("Depth=(%s)",
DepthAttachmentToString(depth_.value()).c_str());
}
if (stencil_) {
stream << ",";
stream << SPrintF("Stencil=(%s)",
StencilAttachmentToString(stencil_.value()).c_str());
}
return stream.str();
}
} // namespace impeller

View File

@ -109,6 +109,8 @@ class RenderTarget final {
void IterateAllAttachments(
const std::function<bool(const Attachment& attachment)>& iterator) const;
std::string ToString() const;
private:
std::map<size_t, ColorAttachment> colors_;
std::optional<DepthAttachment> depth_;