#!/usr/bin/env python3 # Copyright (c) 2019 Collabora Ltd # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # SPDX-License-Identifier: MIT import sys from pathlib import Path import renderdoc as rd def findDrawWithEventId(controller, eventId): for d in controller.GetDrawcalls(): if d.eventId == eventId: return d return None def dumpImage(controller, eventId, outputDir, tracefile): draw = findDrawWithEventId(controller, eventId) if draw is None: raise RuntimeError("Couldn't find draw call with eventId " + str(eventId)) controller.SetFrameEvent(draw.eventId, True) texsave = rd.TextureSave() # Select the first color output texsave.resourceId = draw.outputs[0] if texsave.resourceId == rd.ResourceId.Null(): return filepath = Path(outputDir) filepath.mkdir(parents = True, exist_ok = True) filepath = filepath / (tracefile + "-" + str(int(draw.eventId)) + ".png") print("Saving image at eventId %d: %s to %s" % (draw.eventId, draw.name, filepath)) # Most formats can only display a single image per file, so we select the # first mip and first slice texsave.mip = 0 texsave.slice.sliceIndex = 0 # For formats with an alpha channel, preserve it texsave.alpha = rd.AlphaMapping.Preserve texsave.destType = rd.FileType.PNG controller.SaveTexture(texsave, str(filepath)) def loadCapture(filename): cap = rd.OpenCaptureFile() status = cap.OpenFile(filename, '', None) if status != rd.ReplayStatus.Succeeded: raise RuntimeError("Couldn't open file: " + str(status)) if not cap.LocalReplaySupport(): raise RuntimeError("Capture cannot be replayed") status,controller = cap.OpenCapture(rd.ReplayOptions(), None) if status != rd.ReplayStatus.Succeeded: raise RuntimeError("Couldn't initialise replay: " + str(status)) return (cap, controller) def renderdoc_dump_images(filename, eventIds, outputDir): rd.InitGlobalEnv(rd.GlobalEnvironment(), []) cap,controller = loadCapture(filename); tracefile = Path(filename).name if len(eventIds) == 0: eventIds.append(controller.GetDrawcalls()[-1].eventId) for eventId in eventIds: dumpImage(controller, eventId, outputDir, tracefile) controller.Shutdown() cap.Shutdown() if __name__ == "__main__": if len(sys.argv) < 3: raise RuntimeError("Usage: renderdoc_dump_images.py [...]") eventIds = [int(e) for e in sys.argv[3:]] renderdoc_dump_images(sys.argv[1], eventIds, sys.argv[2])