Skip to content

Commit 47a7180

Browse files
committed
Improve renderpass handling
1 parent d6ef99a commit 47a7180

File tree

13 files changed

+195
-23
lines changed

13 files changed

+195
-23
lines changed

layer_gpu_timeline/android_build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ cmake \
6767
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake" \
6868
..
6969

70-
make -j1
70+
make -j8
7171

7272
popd
7373

layer_gpu_timeline/docs/command_buffer_model.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ performed.
2121

2222
* Pop the latest marker from the queue debug label stack.
2323

24-
**RENDERPASS_BEGIN(const json\*):**
24+
**RENDER_PASS(const json\*):**
2525

2626
* Set the current workload to a new render pass with the passed metadata.
2727

layer_gpu_timeline/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ add_library(
5757
target_include_directories(
5858
${VK_LAYER} PRIVATE
5959
${PROJECT_SOURCE_DIR}/../source_common
60+
${PROJECT_SOURCE_DIR}/../source_third_party
6061
${CMAKE_CURRENT_BINARY_DIR}
6162
.)
6263

layer_gpu_timeline/source/device.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ class Device
130130
*/
131131
~Device();
132132

133+
/**
134+
* @brief Callback for sending messages
135+
*/
136+
void onFrame(const std::string& message)
137+
{
138+
commsWrapper->txMessage(message);
139+
}
140+
133141
/**
134142
* @brief Callback for sending messages
135143
*/

layer_gpu_timeline/source/layer_device_functions_queue.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@
2727
#include <mutex>
2828
#include <thread>
2929

30+
#include "utils/misc.hpp"
31+
#include "nlohmann/json.hpp"
32+
3033
#include "device.hpp"
3134
#include "layer_device_functions.hpp"
32-
#include "utils/misc.hpp"
35+
36+
using json = nlohmann::json;
37+
38+
using namespace std::placeholders;
3339

3440
extern std::mutex g_vulkanLock;
3541

@@ -48,6 +54,15 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkQueuePresentKHR<user_tag>(
4854
auto& tracker = layer->getStateTracker();
4955
tracker.queuePresent();
5056

57+
// This is run with the lock held to ensure that all queue submit
58+
// messages are sent sequentially to the host tool
59+
json frame {
60+
{ "type", "frame" },
61+
{ "fid", tracker.totalStats.getFrameCount() }
62+
};
63+
64+
layer->onFrame(frame.dump());
65+
5166
// Release the lock to call into the driver
5267
lock.unlock();
5368
return layer->driver.vkQueuePresentKHR(queue, pPresentInfo);
@@ -67,20 +82,20 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkQueueSubmit<user_tag>(
6782
std::unique_lock<std::mutex> lock { g_vulkanLock };
6883
auto* layer = Device::retrieve(queue);
6984

70-
using namespace std::placeholders;
7185
auto onSubmit = std::bind(&Device::onWorkloadSubmit, layer, _1);
7286

7387
auto& tracker = layer->getStateTracker();
7488
auto& trackQueue = tracker.getQueue(queue);
7589

90+
// This is run with the lock held to ensure that all queue submit
91+
// messages are sent sequentially to the host tool
7692
for (uint32_t i = 0; i < submitCount; i++)
7793
{
7894
const auto& submit = pSubmits[i];
7995
for (uint32_t j = 0; j < submit.commandBufferCount; j++)
8096
{
8197
auto& trackCB = tracker.getCommandBuffer(submit.pCommandBuffers[j]);
8298
const auto& LCS = trackCB.getSubmitCommandStream();
83-
8499
trackQueue.runSubmitCommandStream(LCS, onSubmit);
85100
}
86101
}
@@ -104,6 +119,24 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkQueueSubmit2<user_tag>(
104119
std::unique_lock<std::mutex> lock { g_vulkanLock };
105120
auto* layer = Device::retrieve(queue);
106121

122+
auto onSubmit = std::bind(&Device::onWorkloadSubmit, layer, _1);
123+
124+
auto& tracker = layer->getStateTracker();
125+
auto& trackQueue = tracker.getQueue(queue);
126+
127+
// This is run with the lock held to ensure that all queue submit
128+
// messages are sent sequentially to the host tool
129+
for (uint32_t i = 0; i < submitCount; i++)
130+
{
131+
const auto& submit = pSubmits[i];
132+
for (uint32_t j = 0; j < submit.commandBufferInfoCount; j++)
133+
{
134+
auto& trackCB = tracker.getCommandBuffer(submit.pCommandBufferInfos[j].commandBuffer);
135+
const auto& LCS = trackCB.getSubmitCommandStream();
136+
trackQueue.runSubmitCommandStream(LCS, onSubmit);
137+
}
138+
}
139+
107140
// Release the lock to call into the driver
108141
lock.unlock();
109142
return layer->driver.vkQueueSubmit2(queue, submitCount, pSubmits, fence);
@@ -123,6 +156,24 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkQueueSubmit2KHR<user_tag>(
123156
std::unique_lock<std::mutex> lock { g_vulkanLock };
124157
auto* layer = Device::retrieve(queue);
125158

159+
auto onSubmit = std::bind(&Device::onWorkloadSubmit, layer, _1);
160+
161+
auto& tracker = layer->getStateTracker();
162+
auto& trackQueue = tracker.getQueue(queue);
163+
164+
// This is run with the lock held to ensure that all queue submit
165+
// messages are sent sequentially to the host tool
166+
for (uint32_t i = 0; i < submitCount; i++)
167+
{
168+
const auto& submit = pSubmits[i];
169+
for (uint32_t j = 0; j < submit.commandBufferInfoCount; j++)
170+
{
171+
auto& trackCB = tracker.getCommandBuffer(submit.pCommandBufferInfos[j].commandBuffer);
172+
const auto& LCS = trackCB.getSubmitCommandStream();
173+
trackQueue.runSubmitCommandStream(LCS, onSubmit);
174+
}
175+
}
176+
126177
// Release the lock to call into the driver
127178
lock.unlock();
128179
return layer->driver.vkQueueSubmit2KHR(queue, submitCount, pSubmits, fence);

lgl_host_server.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ def main():
5757
print()
5858

5959
# Start it running
60-
serverThread = threading.Thread(target=server.run)
60+
serverThread = threading.Thread(target=server.run, daemon=True)
6161
serverThread.start()
6262

6363
# Press to exit
6464
try:
65-
input("Press any key to exit ...")
65+
input("Press any key to exit ...\n\n")
6666
except KeyboardInterrupt:
67-
server.stop()
67+
print("Exiting ...")
68+
sys.exit(0)
6869

6970
return 0
7071

lglpy/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def run(self):
123123

124124
# Accept connections from outside
125125
while not self.shutdown:
126-
print('Waiting for connection')
126+
print('Waiting for client connection')
127127
try:
128128
sockfd, _ = listen_sockfd.accept()
129129
except OSError:

lglpy/service_gpu_timeline.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,69 @@
2525
# implements a basic message endpoint for testing.
2626

2727
from lglpy.server import Message
28+
import json
29+
import struct
2830

2931
class GPUTimelineService:
3032

3133
def __init__(self):
32-
pass
34+
self.frame = {
35+
"frame": 0,
36+
"workloads": [
37+
38+
]
39+
}
40+
41+
# TODO: Make file name configurable
42+
self.fileHandle = open('malivision.gputl', 'wb')
3343

3444
def get_service_name(self) -> str:
3545
return 'GPUTimeline'
3646

47+
def handle_frame(self, msg):
48+
print(json.dumps(self.frame, indent=4))
49+
50+
# Write frame packet to the file
51+
lastFrame = json.dumps(self.frame).encode('utf-8')
52+
length = struct.pack('<I', len(lastFrame))
53+
54+
self.fileHandle.write(length)
55+
self.fileHandle.write(lastFrame)
56+
57+
# Reset the local frame state for the next frame
58+
self.frame = {
59+
'frame': msg['fid'],
60+
'workloads': []
61+
}
62+
63+
def handle_renderpass(self, msg):
64+
# Find the last workload
65+
lastRenderPass = None
66+
if len(self.frame['workloads']):
67+
lastWorkload = self.frame['workloads'][-1]
68+
if lastWorkload['type'] == 'renderpass':
69+
lastRenderPass = lastWorkload
70+
71+
# Continuation
72+
if lastRenderPass and lastRenderPass['tid'] == msg['tid']:
73+
lastRenderPass['drawCallCount'] += msg['drawCallCount']
74+
# New render pass
75+
else:
76+
self.frame['workloads'].append(msg)
77+
3778
def handle_message(self, message: Message):
3879
payload = message.payload.decode('utf-8')
80+
parsedPayload = json.loads(payload)
81+
82+
payloadType = parsedPayload['type']
83+
84+
if payloadType == 'frame':
85+
self.handle_frame(parsedPayload)
86+
87+
elif payloadType == 'renderpass':
88+
self.handle_renderpass(parsedPayload)
3989

40-
print(f'{message.message_type.name}: {payload} ({len(payload)} bytes)')
90+
else:
91+
assert False, f'Unknown payload type {payloadType}'
4192

4293
return None

source_common/trackers/command_buffer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ uint64_t CommandBuffer::renderPassBegin(
9191
// Assign ID and update the stats tracker for new render passes only
9292
if (!resuming)
9393
{
94-
tagID = Tracker::LCSWorkload::getTagID();
94+
tagID = Tracker::LCSWorkload::assignTagID();
9595
stats.incRenderPassCount();
9696
}
9797

@@ -105,7 +105,7 @@ uint64_t CommandBuffer::renderPassBegin(
105105
workloads.push_back(workload);
106106

107107
// Add a command to the layer-side command stream
108-
auto instr = std::make_pair(LCSOpcode::RENDERPASS_BEGIN, workload);
108+
auto instr = std::make_pair(LCSOpcode::RENDER_PASS, workload);
109109
workloadCommandStream.push_back(instr);
110110

111111
return tagID;

source_common/trackers/layer_command_stream.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ LCSRenderPass::LCSRenderPass(
7171

7272
/* See header for details. */
7373
std::string LCSRenderPass::getBeginMetadata(
74+
const std::string* debugLabel,
7475
uint64_t submitID) const
7576
{
7677
json metadata = {
@@ -86,6 +87,11 @@ std::string LCSRenderPass::getBeginMetadata(
8687
metadata["sid"] = submitID;
8788
}
8889

90+
if (debugLabel && debugLabel->size())
91+
{
92+
metadata["label"] = *debugLabel;
93+
}
94+
8995
// Default is 1, so only store if we need it
9096
if (subpassCount != 1)
9197
{
@@ -126,6 +132,7 @@ std::string LCSRenderPass::getBeginMetadata(
126132

127133
/* See header for details. */
128134
std::string LCSRenderPass::getContinuationMetadata(
135+
const std::string* debugLabel,
129136
uint64_t tagIDContinuation,
130137
uint64_t submitID) const
131138
{
@@ -135,6 +142,11 @@ std::string LCSRenderPass::getContinuationMetadata(
135142
{ "drawCallCount", drawCallCount }
136143
};
137144

145+
if (debugLabel && debugLabel->size())
146+
{
147+
metadata["label"] = *debugLabel;
148+
}
149+
138150
if (submitID != 0)
139151
{
140152
metadata["sid"] = submitID;
@@ -145,17 +157,18 @@ std::string LCSRenderPass::getContinuationMetadata(
145157

146158
/* See header for details. */
147159
std::string LCSRenderPass::getMetadata(
160+
const std::string* debugLabel,
148161
uint64_t tagIDContinuation,
149162
uint64_t submitID) const
150163
{
151164
if (tagID)
152165
{
153166
assert(tagIDContinuation == 0);
154-
return getBeginMetadata(submitID);
167+
return getBeginMetadata(debugLabel, submitID);
155168
}
156169

157170
assert(tagIDContinuation != 0);
158-
return getContinuationMetadata(tagIDContinuation, submitID);
171+
return getContinuationMetadata(debugLabel, tagIDContinuation, submitID);
159172
}
160173

161174
}

0 commit comments

Comments
 (0)