mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[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:
parent
b8b3e21214
commit
ea8977d178
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -42,7 +42,10 @@ impeller_component("geometry") {
|
||||
"vector.h",
|
||||
]
|
||||
|
||||
deps = [ "//flutter/fml" ]
|
||||
deps = [
|
||||
"../base",
|
||||
"//flutter/fml",
|
||||
]
|
||||
}
|
||||
|
||||
impeller_component("geometry_asserts") {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user