mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
The Mali Vulkan driver/device was running out of memory internally, occasionally. This adds a hook into the testing window that gets run after each GM finishes, which TestingWindowAndroidVulkan now uses to tear the device down completely. The device then gets rebuilt as needed. Co-authored-by: Josh Jersild <joshua@rive.app>
255 lines
6.6 KiB
C++
255 lines
6.6 KiB
C++
/*
|
|
* Copyright 2022 Rive
|
|
*/
|
|
|
|
#ifndef TESTING_WINDOW_HPP
|
|
#define TESTING_WINDOW_HPP
|
|
|
|
#include "common/offscreen_render_target.hpp"
|
|
#include "rive/renderer/gpu.hpp"
|
|
#include "rive/refcnt.hpp"
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
namespace rive
|
|
{
|
|
class Renderer;
|
|
class Factory;
|
|
namespace gpu
|
|
{
|
|
class RenderContext;
|
|
class RenderContextGLImpl;
|
|
class RenderTarget;
|
|
class Texture;
|
|
class TextureRenderTarget;
|
|
} // namespace gpu
|
|
}; // namespace rive
|
|
|
|
// Wraps a factory for rive::Renderer and a singleton target for it to render
|
|
// into (GL window, HTML canvas, software buffer, etc.):
|
|
//
|
|
// TestingWindow::Init(type);
|
|
// renderer = TestingWindow::Get()->reset(width, height);
|
|
// ...
|
|
//
|
|
|
|
class TestingWindow
|
|
{
|
|
public:
|
|
enum class Backend
|
|
{
|
|
gl,
|
|
d3d,
|
|
d3d12,
|
|
metal,
|
|
vk,
|
|
|
|
// Vulkan on Metal, aka MoltenVK.
|
|
// (defaults to /usr/local/share/vulkan/icd.d/MoltenVK_icd.json if
|
|
// VK_ICD_FILENAMES is not set.)
|
|
moltenvk,
|
|
|
|
// Swiftshader, Google's CPU implementation of Vulkan.
|
|
// (defaults to ./vk_swiftshader_icd.json if VK_ICD_FILENAMES is not
|
|
// set.)
|
|
swiftshader,
|
|
|
|
angle,
|
|
dawn,
|
|
wgpu,
|
|
rhi,
|
|
coregraphics,
|
|
skia,
|
|
null,
|
|
};
|
|
|
|
enum class ANGLERenderer
|
|
{
|
|
metal,
|
|
d3d11,
|
|
vk,
|
|
gles,
|
|
gl,
|
|
};
|
|
|
|
struct BackendParams
|
|
{
|
|
bool atomic = false;
|
|
bool core = false;
|
|
bool msaa = false;
|
|
bool srgb = false;
|
|
bool clockwise = false;
|
|
bool disableValidationLayers = false;
|
|
bool disableDebugCallbacks = false;
|
|
bool wantVulkanSynchronizationValidation = false;
|
|
|
|
ANGLERenderer angleRenderer =
|
|
#ifdef __APPLE__
|
|
ANGLERenderer::metal;
|
|
#elif defined(_WIN32)
|
|
ANGLERenderer::d3d11;
|
|
#else
|
|
ANGLERenderer::vk;
|
|
#endif
|
|
std::string gpuNameFilter;
|
|
};
|
|
|
|
enum class Visibility
|
|
{
|
|
headless,
|
|
window,
|
|
fullscreen,
|
|
};
|
|
|
|
enum class InputEvent
|
|
{
|
|
KeyPress,
|
|
MouseDown,
|
|
MouseUp,
|
|
MouseMove
|
|
};
|
|
|
|
// Aligns with GLFW's mouse button enum
|
|
enum MouseButton : int
|
|
{
|
|
Left,
|
|
Right,
|
|
Middle,
|
|
// can support more buttons
|
|
};
|
|
|
|
struct InputEventData
|
|
{
|
|
InputEventData() : InputEventData(InputEvent::KeyPress, '\0') {}
|
|
|
|
InputEventData(InputEvent type, float posX, float posY) :
|
|
eventType(type)
|
|
{
|
|
metadata = {.posX = posX, .posY = posY};
|
|
}
|
|
|
|
InputEventData(InputEvent type, char c) : eventType(type)
|
|
{
|
|
metadata = {.key = c};
|
|
}
|
|
|
|
InputEvent eventType;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
// Move & down/up mouse press events all have coords
|
|
float posX;
|
|
float posY;
|
|
};
|
|
|
|
char key;
|
|
} metadata;
|
|
};
|
|
|
|
static const char* BackendName(Backend);
|
|
|
|
static Backend ParseBackend(const char* name, BackendParams*);
|
|
static TestingWindow* Init(Backend,
|
|
const BackendParams&,
|
|
Visibility,
|
|
void* platformWindow = nullptr);
|
|
static TestingWindow* Get();
|
|
static void Set(TestingWindow* inWindow);
|
|
static void Destroy();
|
|
|
|
uint32_t width() const { return m_width; }
|
|
uint32_t height() const { return m_height; }
|
|
|
|
virtual rive::Factory* factory() = 0;
|
|
virtual void resize(int width, int height)
|
|
{
|
|
m_width = width;
|
|
m_height = height;
|
|
}
|
|
|
|
// This is called by the gm testing after each GM runs
|
|
virtual void onceAfterGM() {}
|
|
|
|
struct FrameOptions
|
|
{
|
|
uint32_t clearColor;
|
|
bool doClear = true;
|
|
bool forceMSAA = false;
|
|
bool disableRasterOrdering = false;
|
|
bool wireframe = false;
|
|
bool clockwiseFillOverride = false;
|
|
#ifdef WITH_RIVE_TOOLS
|
|
rive::gpu::SynthesizedFailureType synthesizedFailureType =
|
|
rive::gpu::SynthesizedFailureType::none;
|
|
#endif
|
|
};
|
|
virtual std::unique_ptr<rive::Renderer> beginFrame(const FrameOptions&) = 0;
|
|
virtual void endFrame(std::vector<uint8_t>* pixelData = nullptr) = 0;
|
|
|
|
// For testing directly on RenderContext.
|
|
virtual rive::gpu::RenderContext* renderContext() const { return nullptr; }
|
|
virtual rive::gpu::RenderContextGLImpl* renderContextGLImpl() const
|
|
{
|
|
return nullptr;
|
|
}
|
|
virtual rive::gpu::RenderTarget* renderTarget() const { return nullptr; }
|
|
|
|
// Creates a new render target, for testing offscreen rendering.
|
|
// If riveRenderable is false, the texture will lack features required by
|
|
// Rive for rendering directly to it (e.g., input attachment, UAV, etc.),
|
|
// which will exercise indirect rendering fallbacks.
|
|
virtual rive::rcp<rive_tests::OffscreenRenderTarget>
|
|
makeOffscreenRenderTarget(uint32_t width,
|
|
uint32_t height,
|
|
bool riveRenderable) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// For testing render pass breaks. Caller must call
|
|
// renderContext()->beginFrame() again.
|
|
virtual void flushPLSContext(
|
|
rive::gpu::RenderTarget* offscreenRenderTarget = nullptr)
|
|
{}
|
|
|
|
virtual bool consumeInputEvent(InputEventData& eventData) { return false; }
|
|
virtual InputEventData waitForInputEvent()
|
|
{
|
|
fprintf(stderr, "TestingWindow::waitForInputEvent not implemented.");
|
|
abort();
|
|
}
|
|
|
|
virtual bool shouldQuit() const { return false; }
|
|
|
|
virtual void hotloadShaders() {}
|
|
|
|
virtual ~TestingWindow() {}
|
|
|
|
static TestingWindow* MakeEGL(Backend,
|
|
const BackendParams&,
|
|
void* platformWindow);
|
|
#if defined(__APPLE__) && !defined(RIVE_UNREAL)
|
|
static TestingWindow* MakeMetalTexture(const BackendParams&);
|
|
#endif
|
|
static TestingWindow* MakeCoreGraphics();
|
|
static TestingWindow* MakeFiddleContext(Backend,
|
|
const BackendParams&,
|
|
Visibility,
|
|
void* platformWindow);
|
|
static TestingWindow* MakeVulkanTexture(const BackendParams&);
|
|
static TestingWindow* MakeAndroidVulkan(const BackendParams&,
|
|
void* platformWindow);
|
|
static TestingWindow* MakeWGPU(const BackendParams&);
|
|
static TestingWindow* MakeSkia();
|
|
static TestingWindow* MakeNULL();
|
|
|
|
protected:
|
|
uint32_t m_width = 0;
|
|
uint32_t m_height = 0;
|
|
};
|
|
|
|
#endif
|