Skip to content

Commit

Permalink
Improve rendering interface
Browse files Browse the repository at this point in the history
  • Loading branch information
kunitoki committed Apr 30, 2024
1 parent 5c224d2 commit 7e42343
Show file tree
Hide file tree
Showing 8 changed files with 17 additions and 127 deletions.
3 changes: 3 additions & 0 deletions cmake/yup.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ function (_yup_module_collect_sources folder output_variable)
if (NOT "${yup_platform}" MATCHES "^(android)$")
list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_android${extension}")
endif()
if (NOT "${yup_platform}" MATCHES "^(emscripten)$")
list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_emscripten${extension}")
endif()

foreach (source ${found_source_files})
list (APPEND all_module_sources ${source})
Expand Down
6 changes: 5 additions & 1 deletion modules/yup_graphics/native/yup_LowLevelRenderContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,18 @@ class JUCE_API LowLevelRenderContext

virtual void flushPLSContext() = 0; // Called by end()

virtual void end (void* nativeHandle, std::vector<uint8_t>* pixelData = nullptr) = 0;
virtual void end (void* nativeHandle) = 0;

virtual void tick() {}

/**
* @brief OpenGL renderer.
*/
#if JUCE_LINUX || JUCE_WASM || JUCE_ANDROID
static std::unique_ptr<LowLevelRenderContext> makeGLPLS();
#else
static std::unique_ptr<LowLevelRenderContext> makeGLPLS() { return nullptr; }
#endif

/**
* @brief Metal renderer.
Expand Down
36 changes: 2 additions & 34 deletions modules/yup_graphics/native/yup_LowLevelRenderContext_d3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,42 +108,10 @@ class LowLevelRenderContextD3DPLS : public LowLevelRenderContext
m_plsContext->flush({.renderTarget = m_renderTarget.get()});
}

void end(void*, std::vector<uint8_t>* pixelData = nullptr) override
void end(void*) override
{
flushPLSContext();
if (pixelData != nullptr)
{
uint32_t w = m_renderTarget->width();
uint32_t h = m_renderTarget->height();
if (m_readbackTexture == nullptr)
{
D3D11_TEXTURE2D_DESC readbackTexDesc{};
readbackTexDesc.Width = w;
readbackTexDesc.Height = h;
readbackTexDesc.MipLevels = 1;
readbackTexDesc.ArraySize = 1;
readbackTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
readbackTexDesc.SampleDesc.Count = 1;
readbackTexDesc.Usage = D3D11_USAGE_STAGING;
readbackTexDesc.BindFlags = 0;
readbackTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
readbackTexDesc.MiscFlags = 0;
VERIFY_OK(m_gpu->CreateTexture2D(&readbackTexDesc,
nullptr,
m_readbackTexture.ReleaseAndGetAddressOf()));
}

D3D11_MAPPED_SUBRESOURCE map;
m_gpuContext->CopyResource(m_readbackTexture.Get(), m_renderTarget->targetTexture());
m_gpuContext->Map(m_readbackTexture.Get(), 0, D3D11_MAP_READ, 0, &map);
pixelData->resize(h * w * 4);
for (int y = 0; y < h; ++y)
{
auto row = reinterpret_cast<const char*>(map.pData) + map.RowPitch * y;
memcpy(pixelData->data() + (h - y - 1) * w * 4, row, w * 4);
}
m_gpuContext->Unmap(m_readbackTexture.Get(), 0);
}

m_swapchain->Present(0, 0);

m_renderTarget->setTargetTexture(nullptr);
Expand Down
86 changes: 1 addition & 85 deletions modules/yup_graphics/native/yup_LowLevelRenderContext_dawn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,94 +238,10 @@ class LowLevelRenderContextDawnPLS : public LowLevelRenderContext
m_plsContext->beginFrame(std::move(frameDescriptor));
}

void end(GLFWwindow* window, std::vector<uint8_t>* pixelData) final
void end(GLFWwindow* window) final
{
m_plsContext->flush();

if (pixelData != nullptr)
{
// Read back pixels from the framebuffer!
uint32_t w = m_renderTarget->width();
uint32_t h = m_renderTarget->height();
uint32_t rowBytesInReadBuff = math::round_up_to_multiple_of<256>(w * 4);

// Create a buffer to receive the pixels.
if (!m_pixelReadBuff)
{
wgpu::BufferDescriptor buffDesc{
.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst,
.size = h * rowBytesInReadBuff,
};
m_pixelReadBuff = m_device.CreateBuffer(&buffDesc);
}
assert(m_pixelReadBuff.GetSize() == h * rowBytesInReadBuff);

// Blit the framebuffer into m_pixelReadBuff.
wgpu::CommandEncoder readEncoder = m_device.CreateCommandEncoder();
wgpu::ImageCopyTexture srcTexture = {
.texture = m_swapchain.GetCurrentTexture(),
.origin = {0, 0, 0},
};
wgpu::ImageCopyBuffer dstBuffer = {
.layout =
{
.offset = 0,
.bytesPerRow = rowBytesInReadBuff,
},
.buffer = m_pixelReadBuff,
};
wgpu::Extent3D copySize = {
.width = w,
.height = h,
};
readEncoder.CopyTextureToBuffer(&srcTexture, &dstBuffer, &copySize);

wgpu::CommandBuffer commands = readEncoder.Finish();
m_queue.Submit(1, &commands);

// Request a mapping of m_pixelReadBuff and wait for it to complete.
bool mapped = false;
m_pixelReadBuff.MapAsync(
wgpu::MapMode::Read,
0,
h * rowBytesInReadBuff,
[](WGPUBufferMapAsyncStatus status, void* mapped) {
if (status != WGPUBufferMapAsyncStatus_Success)
{
fprintf(stderr, "failed to map m_pixelReadBuff\n");
exit(-1);
}
*reinterpret_cast<bool*>(mapped) = true;
},
&mapped);
while (!mapped)
{
// Spin until the GPU is finished with m_pixelReadBuff and we can read it.
std::this_thread::sleep_for(std::chrono::milliseconds(1));
tick();
}

// Copy the image data from m_pixelReadBuff to pixelData.
pixelData->resize(h * w * 4);
const uint8_t* pixelReadBuffData =
reinterpret_cast<const uint8_t*>(m_pixelReadBuff.GetConstMappedRange());
for (size_t y = 0; y < h; ++y)
{
// Flip Y.
const uint8_t* src = &pixelReadBuffData[(h - y - 1) * rowBytesInReadBuff];
size_t row = y * w * 4;
for (size_t x = 0; x < w * 4; x += 4)
{
// BGBRA -> RGBA.
(*pixelData)[row + x + 0] = src[x + 2];
(*pixelData)[row + x + 1] = src[x + 1];
(*pixelData)[row + x + 2] = src[x + 0];
(*pixelData)[row + x + 3] = src[x + 3];
}
}
m_pixelReadBuff.Unmap();
}

m_swapchain.Present();
}

Expand Down
3 changes: 2 additions & 1 deletion modules/yup_graphics/native/yup_LowLevelRenderContext_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ class LowLevelRenderContextGLPLS : public LowLevelRenderContext
m_plsContext->flush({ .renderTarget = m_renderTarget.get() });
}

void end (void*, std::vector<uint8_t>*) final
void end (void*) final
{
flushPLSContext();

m_plsContext->static_impl_cast<PLSRenderContextGLImpl>()->unbindGLInternalResources();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class LowLevelRenderContextMetalPLS : public LowLevelRenderContext
[flushCommandBuffer commit];
}

void end(void*, std::vector<uint8_t>*) final
void end(void*) final
{
flushPLSContext();

Expand Down
4 changes: 1 addition & 3 deletions modules/yup_graphics/yup_graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,11 @@

#if JUCE_WINDOWS
#include "native/yup_LowLevelRenderContext_d3d.cpp"
#include "native/yup_LowLevelRenderContext_gl.cpp"

#elif JUCE_MAC || JUCE_IOS
#include "native/yup_LowLevelRenderContext_metal.cpp"
#include "native/yup_LowLevelRenderContext_gl.cpp"

#else
#elif JUCE_LINUX || JUCE_WASM || JUCE_ANDROID
#include "native/yup_LowLevelRenderContext_gl.cpp"

#endif
Expand Down
4 changes: 2 additions & 2 deletions thirdparty/rive_pls_renderer/rive_pls_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
#include "source/pls_paint.cpp"
#include "source/pls_render_context_helper_impl.cpp"
#include "source/pls.cpp"
#include "source/intersection_board.cpp"
#include "source/pls_image.cpp"
#include "source/pls_render_context.cpp"
#include "source/pls_draw.cpp"
#include "source/pls_factory.cpp"
#include "source/gr_triangulator.cpp"
#include "source/pls_path.cpp"
#include "source/pls_renderer.cpp"
#include "source/intersection_board.cpp"
#include "source/gr_triangulator.cpp"

#if __clang__
#pragma clang diagnostic pop
Expand Down

0 comments on commit 7e42343

Please sign in to comment.