Add microprofile support (#11403) c83919a247

* Initial commit

* Update macros

* Add GPU Markers

* Fix builds without microprofile

* minor updates

* clang format

* Update profiler.cpp

* clang format

* Name Main Thread

* Update profiler_macros.h

* Fix end flip

* Update fiddle_context_gl.cpp

* clang format

* Update rive_build_config.lua

* Update rive_build_config.lua

* forked microprofile so I can use a tag

* Update render_context_d3d_impl.cpp

* clang

Co-authored-by: John White <aliasbinman@gmail.com>
This commit is contained in:
aliasbinman
2026-01-16 18:31:42 +00:00
parent 9617565e7c
commit decf2d683d
15 changed files with 305 additions and 126 deletions

View File

@@ -1 +1 @@
28e95e51e7823ed149fa5fc323ccc9751bca5356 c83919a2477577deac9afdc2f22b83b9093e4b93

View File

@@ -143,6 +143,13 @@ if _OPTIONS['with_optick'] then
defines({ 'RIVE_OPTICK' }) defines({ 'RIVE_OPTICK' })
RIVE_OPTICK_URL = 'bombomby/optick' RIVE_OPTICK_URL = 'bombomby/optick'
RIVE_OPTICK_VERSION = '1.4.0.0' RIVE_OPTICK_VERSION = '1.4.0.0'
end
newoption({ trigger = 'with_microprofile', description = 'use microprofile profiler' })
if _OPTIONS['with_microprofile'] then
defines({ 'RIVE_MICROPROFILE' })
RIVE_MICROPROFILE_URL = 'aliasbinman/microprofile'
RIVE_MICROPROFILE_VERSION = 'rivebuild'
end end
location(RIVE_BUILD_OUT) location(RIVE_BUILD_OUT)

11
dependencies/premake5_microprofile.lua vendored Normal file
View File

@@ -0,0 +1,11 @@
local dependency = require('dependency')
microprofile = dependency.github(RIVE_MICROPROFILE_URL, RIVE_MICROPROFILE_VERSION)
project('microprofile')
do
kind('StaticLib')
language('C++')
cppdialect('C++11')
files { microprofile .. "/src/embed.c" }
includedirs(microprofile)
end

View File

@@ -14,17 +14,65 @@
// Add to new threads // Add to new threads
#if defined(RIVE_OPTICK) // Optick integration #if defined(RIVE_OPTICK) // Optick integration
#include "optick_core.h" #include "optick_core.h"
#include "optick.h" #include "optick.h"
#define RIVE_PROF_INIT()
#define RIVE_PROF_FRAME() OPTICK_FRAME("RiveFrame") #define RIVE_PROF_FRAME() OPTICK_FRAME("RiveFrame")
#define RIVE_PROF_SCOPE() OPTICK_EVENT() #define RIVE_PROF_SCOPE() OPTICK_EVENT()
#define RIVE_PROF_SCOPENAME(name) OPTICK_EVENT(name) #define RIVE_PROF_SCOPENAME(name) OPTICK_EVENT(name)
#define RIVE_PROF_GPUNAME(name)
#define RIVE_PROF_TAG(cat, tag) OPTICK_TAG(cat, tag) #define RIVE_PROF_TAG(cat, tag) OPTICK_TAG(cat, tag)
#define RIVE_PROF_THREAD(name) OPTICK_THREAD(name) #define RIVE_PROF_THREAD(name) OPTICK_THREAD(name)
#define RIVE_PROF_DRAW()
#define RIVE_PROF_TOGGLEDRAW()
#define RIVE_PROF_GPUSUBMIT(i)
#define RIVE_PROF_GPUFLIP()
#define RIVE_PROF_ENDFRAME()
#elif defined(RIVE_MICROPROFILE) // Microprofile integration
#include "microprofile.h"
#include "microprofiledraw.h"
#include "microprofileui.h"
#define MICROPROFILE_WEBSERVER 1
#define MICROPROFILE_GPU_TIMERS 1
#define RIVE_PROF_INIT() \
MicroProfileSetEnableAllGroups(true); \
MicroProfileSetForceEnable(true); \
MicroProfileWebServerStart(); \
MicroProfileOnThreadCreate("MainThread"); \
MicroProfileInit();
#define RIVE_PROF_FRAME()
#define RIVE_PROF_SCOPE() \
MICROPROFILE_SCOPEI(__FILE__, __FUNCTION__, 0xffffffff);
#define RIVE_PROF_SCOPENAME(name) \
MICROPROFILE_SCOPEI("group", name, 0xffffffff);
#define RIVE_PROF_GPUNAME(name) MICROPROFILE_SCOPEGPUI(name, 0xffffffff);
#define RIVE_PROF_TAG(cat, tag)
#define RIVE_PROF_THREAD(name)
#define RIVE_PROF_DRAW() MicroProfileDraw();
#define RIVE_PROF_TOGGLEDRAW() // MicroProfileToggleDisplayMode();
#define RIVE_PROF_GPUSUBMIT(i) MicroProfileGpuSubmit(i);
#define RIVE_PROF_GPUFLIP() // MicroProfileGpuFlip();
#define RIVE_PROF_ENDFRAME() MicroProfileFlip();
#else // No profiler selected - fallback to no-op #else // No profiler selected - fallback to no-op
#define RIVE_PROF_INIT()
#define RIVE_PROF_FRAME() #define RIVE_PROF_FRAME()
#define RIVE_PROF_SCOPE() #define RIVE_PROF_SCOPE()
#define RIVE_PROF_SCOPENAME(name) #define RIVE_PROF_SCOPENAME(name)
#define RIVE_PROF_GPUNAME(name)
#define RIVE_PROF_TAG(cat, tag) #define RIVE_PROF_TAG(cat, tag)
#define RIVE_PROF_THREAD(name) #define RIVE_PROF_THREAD(name)
#define RIVE_PROF_DRAW()
#define RIVE_PROF_TOGGLEDRAW()
#define RIVE_PROF_GPUSUBMIT(i)
#define RIVE_PROF_GPUFLIP()
#define RIVE_PROF_ENDFRAME()
#endif #endif

View File

@@ -42,6 +42,11 @@ if _OPTIONS['with_optick'] then
dofile(path.join(dependencies, 'premake5_optick.lua')) dofile(path.join(dependencies, 'premake5_optick.lua'))
end end
if _OPTIONS['with_microprofile'] then
dofile(path.join(dependencies, 'premake5_microprofile.lua'))
end
if _OPTIONS['with_rive_scripting'] then if _OPTIONS['with_rive_scripting'] then
local scripting = require(path.join(path.getabsolute('scripting/'), 'premake5')) local scripting = require(path.join(path.getabsolute('scripting/'), 'premake5'))
luau = scripting.luau luau = scripting.luau
@@ -125,6 +130,10 @@ do
includedirs({ optick .. '/src' }) includedirs({ optick .. '/src' })
end end
if _OPTIONS['with_microprofile'] then
includedirs({microprofile})
end
filter('system:macosx or system:ios') filter('system:macosx or system:ios')
do do
files({ 'src/text/font_hb_apple.mm' }) files({ 'src/text/font_hb_apple.mm' })

View File

@@ -193,6 +193,8 @@ public:
if (!m_isHeadless) if (!m_isHeadless)
m_swapchain->Present(0, 0); m_swapchain->Present(0, 0);
RIVE_PROF_ENDFRAME()
m_renderTarget->setTargetTexture(nullptr); m_renderTarget->setTargetTexture(nullptr);
} }

View File

@@ -1,4 +1,5 @@
#include "fiddle_context.hpp" #include "fiddle_context.hpp"
#include "rive/profiler/profiler_macros.h"
#if !defined(_WIN32) || defined(RIVE_UNREAL) #if !defined(_WIN32) || defined(RIVE_UNREAL)
@@ -160,6 +161,10 @@ public:
IID_PPV_ARGS(&m_copyCommandQueue))); IID_PPV_ARGS(&m_copyCommandQueue)));
NAME_RAW_D3D12_OBJECT(m_copyCommandQueue); NAME_RAW_D3D12_OBJECT(m_copyCommandQueue);
#if defined(RIVE_MICROPROFILE)
MicroProfileGpuInitD3D12(m_device.Get(), m_commandQueue.Get());
#endif
for (auto i = 0; i < FrameCount; ++i) for (auto i = 0; i < FrameCount; ++i)
{ {
VERIFY_OK(m_device->CreateCommandAllocator( VERIFY_OK(m_device->CreateCommandAllocator(
@@ -431,6 +436,9 @@ public:
VERIFY_OK(m_commandQueue->Signal(m_fence.Get(), VERIFY_OK(m_commandQueue->Signal(m_fence.Get(),
m_previousFrames[m_frameIndex])); m_previousFrames[m_frameIndex]));
RIVE_PROF_GPUSUBMIT(0);
RIVE_PROF_ENDFRAME()
} }
void flushPLSContext(RenderTarget* offscreenRenderTarget) final void flushPLSContext(RenderTarget* offscreenRenderTarget) final
@@ -447,7 +455,9 @@ public:
VERIFY_OK(m_copyCommandList->Reset(m_copyAllocators[m_frameIndex].Get(), VERIFY_OK(m_copyCommandList->Reset(m_copyAllocators[m_frameIndex].Get(),
NULL)); NULL));
#if defined(RIVE_MICROPROFILE)
MicroProfileGpuSetContext(m_commandList.Get());
#endif
RenderContextD3D12Impl::CommandLists cmdLists = { RenderContextD3D12Impl::CommandLists cmdLists = {
m_copyCommandList.Get(), m_copyCommandList.Get(),
m_commandList.Get()}; m_commandList.Get()};
@@ -575,6 +585,8 @@ public:
if (!m_isHeadless) if (!m_isHeadless)
m_swapChain->Present(0, 0); m_swapChain->Present(0, 0);
RIVE_PROF_GPUFLIP();
} }
private: private:

View File

@@ -13,6 +13,7 @@ std::unique_ptr<FiddleContext> FiddleContext::MakeGLPLS(FiddleContextOptions)
#include "rive/renderer/rive_renderer.hpp" #include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/gl/render_context_gl_impl.hpp" #include "rive/renderer/gl/render_context_gl_impl.hpp"
#include "rive/renderer/gl/render_target_gl.hpp" #include "rive/renderer/gl/render_target_gl.hpp"
#include "rive/profiler/profiler_macros.h"
#ifdef RIVE_WEBGL #ifdef RIVE_WEBGL
#include <emscripten/emscripten.h> #include <emscripten/emscripten.h>
@@ -169,6 +170,7 @@ public:
GL_NEAREST); GL_NEAREST);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
RIVE_PROF_ENDFRAME()
} }
protected: protected:

View File

@@ -341,7 +341,15 @@ static void key_callback(GLFWwindow* window,
clockwiseFill = !clockwiseFill; clockwiseFill = !clockwiseFill;
break; break;
case GLFW_KEY_P: case GLFW_KEY_P:
paused = !paused; if (!shift)
{
paused = !paused;
}
else
{
RIVE_PROF_TOGGLEDRAW();
}
break; break;
case GLFW_KEY_H: case GLFW_KEY_H:
if (!shift) if (!shift)
@@ -427,6 +435,8 @@ int main(int argc, const char** argv)
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);
RIVE_PROF_INIT()
#ifdef DEBUG #ifdef DEBUG
options.enableVulkanCoreValidationLayers = true; options.enableVulkanCoreValidationLayers = true;
#endif #endif

View File

@@ -94,6 +94,11 @@ if not _OPTIONS['with-webgpu'] then
externalincludedirs({ optick .. '/src'}) externalincludedirs({ optick .. '/src'})
end end
if _OPTIONS['with_microprofile'] then
links({'microprofile'})
externalincludedirs({ microprofile})
end
if rive_target_os == 'windows' then if rive_target_os == 'windows' then
externalincludedirs({ externalincludedirs({
dx12_headers .. '/include/directx', dx12_headers .. '/include/directx',

View File

@@ -183,6 +183,10 @@ if _OPTIONS['with_optick'] then
optick = dependency.github(RIVE_OPTICK_URL, RIVE_OPTICK_VERSION) optick = dependency.github(RIVE_OPTICK_URL, RIVE_OPTICK_VERSION)
end end
if _OPTIONS['with_microprofile'] then
microprofile = dependency.github(RIVE_MICROPROFILE_URL, RIVE_MICROPROFILE_VERSION)
end
project('rive_pls_renderer') project('rive_pls_renderer')
do do
kind('StaticLib') kind('StaticLib')
@@ -204,6 +208,10 @@ do
includedirs({optick .. '/src'}) includedirs({optick .. '/src'})
end end
if _OPTIONS['with_microprofile'] then
includedirs({ microprofile })
end
if _OPTIONS['with_vulkan'] then if _OPTIONS['with_vulkan'] then
externalincludedirs({ externalincludedirs({
vulkan_headers .. '/include', vulkan_headers .. '/include',

View File

@@ -7,6 +7,7 @@
#include "rive/renderer/d3d/d3d_constants.hpp" #include "rive/renderer/d3d/d3d_constants.hpp"
#include "rive/renderer/texture.hpp" #include "rive/renderer/texture.hpp"
#include "rive/profiler/profiler_macros.h"
#include <D3DCompiler.h> #include <D3DCompiler.h>
@@ -408,6 +409,9 @@ std::unique_ptr<RenderContext> RenderContextD3DImpl::MakeContext(
ComPtr<ID3D11DeviceContext> gpuContext, ComPtr<ID3D11DeviceContext> gpuContext,
const D3DContextOptions& contextOptions) const D3DContextOptions& contextOptions)
{ {
#if defined(RIVE_MICROPROFILE)
MicroProfileGpuInitD3D11(gpu.Get());
#endif
D3DCapabilities d3dCapabilities; D3DCapabilities d3dCapabilities;
D3D11_FEATURE_DATA_D3D11_OPTIONS2 d3d11Options2; D3D11_FEATURE_DATA_D3D11_OPTIONS2 d3d11Options2;
@@ -1544,6 +1548,8 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
// Tessellate all curves into vertices in the tessellation texture. // Tessellate all curves into vertices in the tessellation texture.
if (desc.tessVertexSpanCount > 0) if (desc.tessVertexSpanCount > 0)
{ {
RIVE_PROF_GPUNAME("Tessellate Curves");
ID3D11Buffer* tessSpanBuffer = ID3D11Buffer* tessSpanBuffer =
flush_buffer(m_gpuContext.Get(), tessSpanBufferRing()); flush_buffer(m_gpuContext.Get(), tessSpanBufferRing());
UINT tessStride = sizeof(TessVertexSpan); UINT tessStride = sizeof(TessVertexSpan);
@@ -1626,6 +1632,8 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
// Render the atlas if we have any offscreen feathers. // Render the atlas if we have any offscreen feathers.
if ((desc.atlasFillBatchCount | desc.atlasStrokeBatchCount) != 0) if ((desc.atlasFillBatchCount | desc.atlasStrokeBatchCount) != 0)
{ {
RIVE_PROF_GPUNAME("atlasRender");
float clearZero[4]{}; float clearZero[4]{};
m_gpuContext->ClearRenderTargetView(m_atlasTextureRTV.Get(), clearZero); m_gpuContext->ClearRenderTargetView(m_atlasTextureRTV.Get(), clearZero);
@@ -1708,60 +1716,70 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
} }
// Setup and clear the PLS textures. // Setup and clear the PLS textures.
switch (desc.colorLoadAction)
{ {
case gpu::LoadAction::clear: RIVE_PROF_GPUNAME("clearPLSTextures");
if (desc.fixedFunctionColorOutput) switch (desc.colorLoadAction)
{ {
float clearColor4f[4];
UnpackColorToRGBA32FPremul(desc.colorClearValue, clearColor4f); case gpu::LoadAction::clear:
m_gpuContext->ClearRenderTargetView(renderTarget->targetRTV(), if (desc.fixedFunctionColorOutput)
clearColor4f); {
} float clearColor4f[4];
else if (m_d3dCapabilities.supportsTypedUAVLoadStore) UnpackColorToRGBA32FPremul(desc.colorClearValue,
{ clearColor4f);
float clearColor4f[4]; m_gpuContext->ClearRenderTargetView(
UnpackColorToRGBA32FPremul(desc.colorClearValue, clearColor4f); renderTarget->targetRTV(),
m_gpuContext->ClearUnorderedAccessViewFloat( clearColor4f);
renderTarget->targetUAV(), }
clearColor4f); else if (m_d3dCapabilities.supportsTypedUAVLoadStore)
} {
else float clearColor4f[4];
{ UnpackColorToRGBA32FPremul(desc.colorClearValue,
UINT clearColorui[4] = { clearColor4f);
gpu::SwizzleRiveColorToRGBAPremul(desc.colorClearValue)}; m_gpuContext->ClearUnorderedAccessViewFloat(
m_gpuContext->ClearUnorderedAccessViewUint( renderTarget->targetUAV(),
renderTarget->targetUAV(), clearColor4f);
clearColorui); }
} else
break; {
case gpu::LoadAction::preserveRenderTarget: UINT clearColorui[4] = {gpu::SwizzleRiveColorToRGBAPremul(
if (!desc.fixedFunctionColorOutput && desc.colorClearValue)};
!renderTarget->targetTextureSupportsUAV()) m_gpuContext->ClearUnorderedAccessViewUint(
{ renderTarget->targetUAV(),
// We're rendering to an offscreen UAV and preserving the clearColorui);
// target. Copy the target texture over. }
blit_sub_rect(m_gpuContext.Get(), break;
renderTarget->offscreenTexture(), case gpu::LoadAction::preserveRenderTarget:
renderTarget->targetTexture(), if (!desc.fixedFunctionColorOutput &&
desc.renderTargetUpdateBounds); !renderTarget->targetTextureSupportsUAV())
} {
break; // We're rendering to an offscreen UAV and preserving the
case gpu::LoadAction::dontCare: // target. Copy the target texture over.
break; blit_sub_rect(m_gpuContext.Get(),
} renderTarget->offscreenTexture(),
if (desc.combinedShaderFeatures & gpu::ShaderFeatures::ENABLE_CLIPPING) renderTarget->targetTexture(),
{ desc.renderTargetUpdateBounds);
constexpr static UINT kZero[4]{}; }
m_gpuContext->ClearUnorderedAccessViewUint(renderTarget->clipUAV(), break;
kZero); case gpu::LoadAction::dontCare:
} break;
{ }
UINT coverageClear[4]{desc.coverageClearValue}; if (desc.combinedShaderFeatures & gpu::ShaderFeatures::ENABLE_CLIPPING)
m_gpuContext->ClearUnorderedAccessViewUint(renderTarget->coverageUAV(), {
coverageClear); constexpr static UINT kZero[4]{};
m_gpuContext->ClearUnorderedAccessViewUint(renderTarget->clipUAV(),
kZero);
}
{
UINT coverageClear[4]{desc.coverageClearValue};
m_gpuContext->ClearUnorderedAccessViewUint(
renderTarget->coverageUAV(),
coverageClear);
}
} }
RIVE_PROF_GPUNAME("DrawList");
// Execute the DrawList. // Execute the DrawList.
ID3D11RenderTargetView* targetRTV = ID3D11RenderTargetView* targetRTV =
desc.fixedFunctionColorOutput ? renderTarget->targetRTV() : NULL; desc.fixedFunctionColorOutput ? renderTarget->targetRTV() : NULL;
@@ -1892,6 +1910,7 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
&drawUniforms, &drawUniforms,
0, 0,
0); 0);
RIVE_PROF_GPUNAME("Patches");
m_gpuContext->DrawIndexedInstanced(PatchIndexCount(drawType), m_gpuContext->DrawIndexedInstanced(PatchIndexCount(drawType),
batch.elementCount, batch.elementCount,
PatchBaseIndex(drawType), PatchBaseIndex(drawType),
@@ -1906,11 +1925,16 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_gpuContext->RSSetState( m_gpuContext->RSSetState(
m_backCulledRasterState[desc.wireframe].Get()); m_backCulledRasterState[desc.wireframe].Get());
RIVE_PROF_GPUNAME(drawType == DrawType::atlasBlit
? "atlasBlit"
: "interiorTriangulation");
m_gpuContext->Draw(batch.elementCount, batch.baseElement); m_gpuContext->Draw(batch.elementCount, batch.baseElement);
break; break;
} }
case DrawType::imageRect: case DrawType::imageRect:
{ {
RIVE_PROF_GPUNAME("imageRect");
m_gpuContext->IASetPrimitiveTopology( m_gpuContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_gpuContext->IASetIndexBuffer(m_imageRectIndexBuffer.Get(), m_gpuContext->IASetIndexBuffer(m_imageRectIndexBuffer.Get(),
@@ -1932,6 +1956,7 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
} }
case DrawType::imageMesh: case DrawType::imageMesh:
{ {
RIVE_PROF_GPUNAME("imageMesh");
LITE_RTTI_CAST_OR_BREAK(vertexBuffer, LITE_RTTI_CAST_OR_BREAK(vertexBuffer,
RenderBufferD3DImpl*, RenderBufferD3DImpl*,
batch.vertexBuffer); batch.vertexBuffer);
@@ -1972,6 +1997,9 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
break; break;
} }
case DrawType::renderPassResolve: case DrawType::renderPassResolve:
{
RIVE_PROF_GPUNAME("renderPassResolve");
assert(desc.interlockMode == gpu::InterlockMode::atomics); assert(desc.interlockMode == gpu::InterlockMode::atomics);
m_gpuContext->IASetPrimitiveTopology( m_gpuContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
@@ -2010,7 +2038,8 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
NULL); NULL);
} }
m_gpuContext->Draw(4, 0); m_gpuContext->Draw(4, 0);
break; }
break;
case DrawType::msaaStrokes: case DrawType::msaaStrokes:
case DrawType::msaaMidpointFanBorrowedCoverage: case DrawType::msaaMidpointFanBorrowedCoverage:
case DrawType::msaaMidpointFans: case DrawType::msaaMidpointFans:
@@ -2027,6 +2056,8 @@ void RenderContextD3DImpl::flush(const FlushDescriptor& desc)
if (desc.interlockMode == gpu::InterlockMode::rasterOrdering && if (desc.interlockMode == gpu::InterlockMode::rasterOrdering &&
!renderTarget->targetTextureSupportsUAV()) !renderTarget->targetTextureSupportsUAV())
{ {
RIVE_PROF_GPUNAME("blit_sub_rect");
// We rendered to an offscreen UAV and did not resolve to the // We rendered to an offscreen UAV and did not resolve to the
// renderTarget. Copy back to the main target. // renderTarget. Copy back to the main target.
assert(!desc.fixedFunctionColorOutput); assert(!desc.fixedFunctionColorOutput);

View File

@@ -4,6 +4,8 @@
#include "rive/renderer/d3d12/render_context_d3d12_impl.hpp" #include "rive/renderer/d3d12/render_context_d3d12_impl.hpp"
#include "rive/renderer/d3d/d3d_constants.hpp" #include "rive/renderer/d3d/d3d_constants.hpp"
#include "rive/profiler/profiler_macros.h"
// needed for root sig and heap constants // needed for root sig and heap constants
#include "shaders/d3d/root.sig" #include "shaders/d3d/root.sig"
@@ -1108,6 +1110,8 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
if (desc.tessVertexSpanCount) if (desc.tessVertexSpanCount)
{ {
RIVE_PROF_GPUNAME("Tessellate Curves");
m_resourceManager->transition(cmdList, m_resourceManager->transition(cmdList,
m_tesselationTexture.get(), m_tesselationTexture.get(),
D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -1190,6 +1194,7 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
if ((desc.atlasFillBatchCount | desc.atlasStrokeBatchCount) != 0) if ((desc.atlasFillBatchCount | desc.atlasStrokeBatchCount) != 0)
{ {
RIVE_PROF_GPUNAME("atlasRender");
m_resourceManager->transition(cmdList, m_resourceManager->transition(cmdList,
m_atlasTexture.get(), m_atlasTexture.get(),
D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -1278,88 +1283,95 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
cmdList->RSSetScissorRects(1, &scissorRect); cmdList->RSSetScissorRects(1, &scissorRect);
// Setup and clear the PLS textures. // Setup and clear the PLS textures.
if (desc.fixedFunctionColorOutput)
{ {
m_resourceManager->transition(cmdList, RIVE_PROF_GPUNAME("clearPLSTextures");
targetTexture, if (desc.fixedFunctionColorOutput)
D3D12_RESOURCE_STATE_RENDER_TARGET);
auto rtvHandle = m_rtvHeap->cpuHandleForIndex(TARGET_RTV_HEAP_OFFSET);
cmdList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
if (desc.colorLoadAction == gpu::LoadAction::clear)
{ {
float clearColor4f[4]; m_resourceManager->transition(cmdList,
UnpackColorToRGBA32FPremul(desc.colorClearValue, clearColor4f); targetTexture,
cmdList->ClearRenderTargetView(rtvHandle, clearColor4f, 0, nullptr); D3D12_RESOURCE_STATE_RENDER_TARGET);
}
}
else // !desc.fixedFunctionColorOutput
{
if (renderTarget->targetTextureSupportsUAV())
{
m_resourceManager->transition(
cmdList,
targetTexture,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
if (desc.colorLoadAction == gpu::LoadAction::clear) auto rtvHandle =
{ m_rtvHeap->cpuHandleForIndex(TARGET_RTV_HEAP_OFFSET);
auto tex = renderTarget->targetTextureSupportsUAV() cmdList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
? renderTarget->targetTexture()->resource()
: renderTarget->offscreenTexture()->resource();
if (m_capabilities.supportsTypedUAVLoadStore) if (desc.colorLoadAction == gpu::LoadAction::clear)
{ {
float clearColor4f[4]; float clearColor4f[4];
UnpackColorToRGBA32FPremul(desc.colorClearValue, clearColor4f); UnpackColorToRGBA32FPremul(desc.colorClearValue, clearColor4f);
cmdList->ClearRenderTargetView(rtvHandle,
auto gpuHandle = m_srvUavCbvHeap->gpuHandleForIndex( clearColor4f,
ATOMIC_COLOR_HEAP_OFFSET); 0,
auto cpuHandle = m_cpuSrvUavCbvHeap->cpuHandleForIndex( nullptr);
ATOMIC_COLOR_HEAP_OFFSET);
m_resourceManager->clearUAV(cmdList,
tex,
gpuHandle,
cpuHandle,
clearColor4f,
desc.interlockMode ==
InterlockMode::atomics);
}
else
{
UINT clearColorui[4] = {
gpu::SwizzleRiveColorToRGBAPremul(desc.colorClearValue)};
auto gpuHandle = m_srvUavCbvHeap->gpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
auto cpuHandle = m_cpuSrvUavCbvHeap->cpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
m_resourceManager->clearUAV(cmdList,
tex,
gpuHandle,
cpuHandle,
clearColorui,
desc.interlockMode ==
InterlockMode::atomics);
} }
} }
if (desc.colorLoadAction == gpu::LoadAction::preserveRenderTarget && else // !desc.fixedFunctionColorOutput
!renderTarget->targetTextureSupportsUAV())
{ {
auto offscreenTex = renderTarget->offscreenTexture(); if (renderTarget->targetTextureSupportsUAV())
blitSubRect(cmdList, {
offscreenTex, m_resourceManager->transition(
renderTarget->targetTexture(), cmdList,
desc.renderTargetUpdateBounds); targetTexture,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
m_resourceManager->transition( if (desc.colorLoadAction == gpu::LoadAction::clear)
cmdList, {
offscreenTex, auto tex = renderTarget->targetTextureSupportsUAV()
D3D12_RESOURCE_STATE_UNORDERED_ACCESS); ? renderTarget->targetTexture()->resource()
: renderTarget->offscreenTexture()->resource();
if (m_capabilities.supportsTypedUAVLoadStore)
{
float clearColor4f[4];
UnpackColorToRGBA32FPremul(desc.colorClearValue,
clearColor4f);
auto gpuHandle = m_srvUavCbvHeap->gpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
auto cpuHandle = m_cpuSrvUavCbvHeap->cpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
m_resourceManager->clearUAV(cmdList,
tex,
gpuHandle,
cpuHandle,
clearColor4f,
desc.interlockMode ==
InterlockMode::atomics);
}
else
{
UINT clearColorui[4] = {gpu::SwizzleRiveColorToRGBAPremul(
desc.colorClearValue)};
auto gpuHandle = m_srvUavCbvHeap->gpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
auto cpuHandle = m_cpuSrvUavCbvHeap->cpuHandleForIndex(
ATOMIC_COLOR_HEAP_OFFSET);
m_resourceManager->clearUAV(cmdList,
tex,
gpuHandle,
cpuHandle,
clearColorui,
desc.interlockMode ==
InterlockMode::atomics);
}
}
if (desc.colorLoadAction == gpu::LoadAction::preserveRenderTarget &&
!renderTarget->targetTextureSupportsUAV())
{
auto offscreenTex = renderTarget->offscreenTexture();
blitSubRect(cmdList,
offscreenTex,
renderTarget->targetTexture(),
desc.renderTargetUpdateBounds);
m_resourceManager->transition(
cmdList,
offscreenTex,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
} }
} }
@@ -1412,6 +1424,7 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
m_heapDescriptorOffset += imageDescriptorOffset; m_heapDescriptorOffset += imageDescriptorOffset;
RIVE_PROF_GPUNAME("DrawList");
for (const DrawBatch& batch : *desc.drawList) for (const DrawBatch& batch : *desc.drawList)
{ {
assert(batch.elementCount != 0); assert(batch.elementCount != 0);
@@ -1544,6 +1557,7 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
case DrawType::midpointFanCenterAAPatches: case DrawType::midpointFanCenterAAPatches:
case DrawType::outerCurvePatches: case DrawType::outerCurvePatches:
{ {
RIVE_PROF_GPUNAME("Patches");
cmdList->IASetPrimitiveTopology( cmdList->IASetPrimitiveTopology(
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
auto IBV = m_pathPatchIndexBuffer->indexBufferView(); auto IBV = m_pathPatchIndexBuffer->indexBufferView();
@@ -1562,6 +1576,7 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
case DrawType::interiorTriangulation: case DrawType::interiorTriangulation:
case DrawType::atlasBlit: case DrawType::atlasBlit:
{ {
RIVE_PROF_GPUNAME("interiorTriangulation||atlasBlit");
cmdList->IASetPrimitiveTopology( cmdList->IASetPrimitiveTopology(
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
cmdList->DrawInstanced(batch.elementCount, cmdList->DrawInstanced(batch.elementCount,
@@ -1572,6 +1587,8 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
} }
case DrawType::imageRect: case DrawType::imageRect:
{ {
RIVE_PROF_GPUNAME("imageRect");
cmdList->IASetPrimitiveTopology( cmdList->IASetPrimitiveTopology(
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
auto IBV = m_imageRectIndexBuffer->indexBufferView(); auto IBV = m_imageRectIndexBuffer->indexBufferView();
@@ -1592,6 +1609,8 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
} }
case DrawType::imageMesh: case DrawType::imageMesh:
{ {
RIVE_PROF_GPUNAME("imageMesh");
LITE_RTTI_CAST_OR_BREAK(vertexBuffer, LITE_RTTI_CAST_OR_BREAK(vertexBuffer,
RenderBufferD3D12Impl*, RenderBufferD3D12Impl*,
batch.vertexBuffer); batch.vertexBuffer);
@@ -1633,11 +1652,16 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
break; break;
} }
case DrawType::renderPassResolve: case DrawType::renderPassResolve:
{
RIVE_PROF_GPUNAME("renderPassResolve");
assert(desc.interlockMode == gpu::InterlockMode::atomics); assert(desc.interlockMode == gpu::InterlockMode::atomics);
cmdList->IASetPrimitiveTopology( cmdList->IASetPrimitiveTopology(
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
cmdList->DrawInstanced(4, 1, 0, 0); cmdList->DrawInstanced(4, 1, 0, 0);
break; break;
}
case DrawType::msaaStrokes: case DrawType::msaaStrokes:
case DrawType::msaaMidpointFanBorrowedCoverage: case DrawType::msaaMidpointFanBorrowedCoverage:
case DrawType::msaaMidpointFans: case DrawType::msaaMidpointFans:
@@ -1654,6 +1678,8 @@ void RenderContextD3D12Impl::flush(const FlushDescriptor& desc)
if (desc.interlockMode == gpu::InterlockMode::rasterOrdering && if (desc.interlockMode == gpu::InterlockMode::rasterOrdering &&
!renderTarget->targetTextureSupportsUAV()) !renderTarget->targetTextureSupportsUAV())
{ {
RIVE_PROF_GPUNAME("blit_sub_rect");
// We rendered to an offscreen UAV and did not resolve to the // We rendered to an offscreen UAV and did not resolve to the
// renderTarget. Copy back to the main target. // renderTarget. Copy back to the main target.
assert(!desc.fixedFunctionColorOutput); assert(!desc.fixedFunctionColorOutput);

View File

@@ -0,0 +1,8 @@
#ifdef RIVE_MICROPROFILE
#define MICROPROFILE_IMPL
#if defined(RIVE_WINDOWS)
#define MICROPROFILE_GPU_TIMERS_D3D11 1
#define MICROPROFILE_GPU_TIMERS_D3D12 1
#endif
#include "microprofile.h"
#endif