From 4c08ea3692e9294d0dedc24016335ba607e9a681 Mon Sep 17 00:00:00 2001 From: pedohorse <13556996+pedohorse@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:49:58 +0200 Subject: [PATCH] houdini stock nodes: use opencl,karma device tags --- .../houdini/nodes/hip_driver_renderer.py | 9 +++- .../houdini/nodes/hip_ifd_generator.py | 9 +++- .../stock_nodes/houdini/nodes/hip_script.py | 9 +++- .../stock_nodes/houdini/nodes/karma.py | 54 +++++++++++-------- .../lifeblood_stock_houdini_helpers/common.py | 51 ++++++++++++++++++ .../rop_base_node.py | 10 +++- 6 files changed, 116 insertions(+), 26 deletions(-) create mode 100644 src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/common.py diff --git a/src/lifeblood/stock_nodes/houdini/nodes/hip_driver_renderer.py b/src/lifeblood/stock_nodes/houdini/nodes/hip_driver_renderer.py index 911e0a6b..6be96791 100644 --- a/src/lifeblood/stock_nodes/houdini/nodes/hip_driver_renderer.py +++ b/src/lifeblood/stock_nodes/houdini/nodes/hip_driver_renderer.py @@ -4,6 +4,7 @@ from lifeblood.nodethings import ProcessingResult, ProcessingError from lifeblood.invocationjob import InvocationJob, InvocationEnvironment from lifeblood.text import filter_by_pattern +from lifeblood_stock_houdini_helpers.common import gpu_device_env_common_code from typing import Iterable @@ -237,8 +238,14 @@ def process_task(self, context) -> ProcessingResult: script += f'print("all done!")\n' - inv = InvocationJob(['hython', ':/work_to_do.py'], env=env) + launch_wrapper_code = ( + gpu_device_env_common_code() + + 'import sys, subprocess\n' + 'sys.exit(subprocess.Popen(sys.argv[1:]).wait())') + + inv = InvocationJob(['python', ':/launch_wrapper.py', 'hython', ':/work_to_do.py'], env=env) inv.set_extra_file('work_to_do.py', script) + inv.set_extra_file('launch_wrapper.py', launch_wrapper_code) res = ProcessingResult(job=inv) return res diff --git a/src/lifeblood/stock_nodes/houdini/nodes/hip_ifd_generator.py b/src/lifeblood/stock_nodes/houdini/nodes/hip_ifd_generator.py index 75f4f16e..75dcf8d9 100644 --- a/src/lifeblood/stock_nodes/houdini/nodes/hip_ifd_generator.py +++ b/src/lifeblood/stock_nodes/houdini/nodes/hip_ifd_generator.py @@ -4,6 +4,7 @@ from lifeblood.nodethings import ProcessingResult, ProcessingError from lifeblood.invocationjob import InvocationJob, InvocationEnvironment from lifeblood.text import filter_by_pattern +from lifeblood_stock_houdini_helpers.common import gpu_device_env_common_code from typing import Iterable @@ -134,8 +135,14 @@ def process_task(self, context) -> ProcessingResult: script += \ f'print("all done!")\n' - inv = InvocationJob(['hython', ':/work_to_do.py'], env=env) + launch_wrapper_code = ( + gpu_device_env_common_code() + + 'import sys, subprocess\n' + 'sys.exit(subprocess.Popen(sys.argv[1:]).wait())') + + inv = InvocationJob(['python', ':/launch_wrapper.py', 'hython', ':/work_to_do.py'], env=env) inv.set_extra_file('work_to_do.py', script) + inv.set_extra_file('launch_wrapper.py', launch_wrapper_code) res = ProcessingResult(job=inv) return res diff --git a/src/lifeblood/stock_nodes/houdini/nodes/hip_script.py b/src/lifeblood/stock_nodes/houdini/nodes/hip_script.py index bc9244bc..9d32d56c 100644 --- a/src/lifeblood/stock_nodes/houdini/nodes/hip_script.py +++ b/src/lifeblood/stock_nodes/houdini/nodes/hip_script.py @@ -3,6 +3,7 @@ from lifeblood.nodethings import ProcessingResult, ProcessingError from lifeblood.invocationjob import InvocationJob, InvocationEnvironment from lifeblood.text import filter_by_pattern +from lifeblood_stock_houdini_helpers.common import gpu_device_env_common_code from typing import Iterable @@ -75,8 +76,14 @@ def process_task(self, context) -> ProcessingResult: '__main_body__()\n' \ f'hou.hipFile.save({repr(dest_hip)})\n' - job = InvocationJob(['hython', ':/work_to_do.py']) + launch_wrapper_code = ( + gpu_device_env_common_code() + + 'import sys, subprocess\n' + 'sys.exit(subprocess.Popen(sys.argv[1:]).wait())') + + job = InvocationJob(['python', ':/launch_wrapper.py', 'hython', ':/work_to_do.py']) job.set_extra_file('work_to_do.py', script) + job.set_extra_file('launch_wrapper.py', launch_wrapper_code) return ProcessingResult(job=job) def postprocess_task(self, context) -> ProcessingResult: diff --git a/src/lifeblood/stock_nodes/houdini/nodes/karma.py b/src/lifeblood/stock_nodes/houdini/nodes/karma.py index d3052ff8..953c43cb 100644 --- a/src/lifeblood/stock_nodes/houdini/nodes/karma.py +++ b/src/lifeblood/stock_nodes/houdini/nodes/karma.py @@ -2,6 +2,7 @@ from lifeblood.enums import NodeParameterType from lifeblood.nodethings import ProcessingResult, ProcessingError from lifeblood.invocationjob import InvocationJob, InvocationEnvironment +from lifeblood_stock_houdini_helpers.common import gpu_device_env_common_code from typing import Iterable @@ -40,6 +41,7 @@ def __init__(self, name): ui = self.get_ui() with ui.initializing_interface_lock(): ui.color_scheme().set_main_color(0.5, 0.25, 0.125) + ui.add_parameter('renderer', 'engine', NodeParameterType.STRING, 'cpu').add_menu((('CPU', 'cpu'), ('XPU', 'xpu'))) ui.add_parameter('usd path', 'usd file path', NodeParameterType.STRING, "`task['file']`") ui.add_parameter('image path', 'output image file path', NodeParameterType.STRING, "`task['outimage']`") ui.add_parameter('skip if exists', 'skip if result already exists', NodeParameterType.BOOL, False) @@ -51,28 +53,36 @@ def process_task(self, context) -> ProcessingResult: args = context.task_attributes() env = InvocationEnvironment() - - if context.param_value('skip if exists'): - script = 'import os\n' \ - 'if not os.path.exists({imgpath}):\n' \ - ' import sys\n' \ - ' from subprocess import Popen\n' \ - " sys.exit(Popen(['husk', '-V', '2a', '--make-output-path',{doframe} '-o', {imgpath}, {usdpath}]).wait())\n" \ - "else:\n" \ - " print('image file already exists, skipping work')\n" \ - .format(imgpath=repr(context.param_value('image path')), - usdpath=repr(context.param_value('usd path')), - doframe=f" '-f', {repr(str(args['frames'][0]))}," if 'frames' in args else '', - ) - - invoc = InvocationJob(['python', ':/karmacall.py']) - invoc.set_extra_file('karmacall.py', script) - else: # TODO: -f there is testing, if succ - make a parameter out of it on the node or smth - invoc = InvocationJob(['husk', '-V', '2a', - '--make-output-path'] + - (['-f', str(args['frames'][0])] if 'frames' in args else []) + - ['-o', context.param_value('image path'), context.param_value('usd path')], - env=env) + delegates_map = { + 'cpu': 'BRAY_HdKarma', + 'xpu': 'BRAY_HdKarmaXPU', + } + default_delegate = 'BRAY_HdKarma' + + do_skip_exists = context.param_value('skip if exists') + script = gpu_device_env_common_code() + \ + 'import os\n' \ + 'if not {do_skip_exists} or not os.path.exists({imgpath}):\n' \ + ' import sys\n' \ + ' from subprocess import Popen\n' \ + " sys.exit(Popen(['husk', '-R', {delegate}, '-V', '2a', '--make-output-path',{doframe} '-o', {imgpath}, {usdpath}]).wait())\n" \ + "else:\n" \ + " print('image file already exists, skipping work')\n" \ + .format(imgpath=repr(context.param_value('image path')), + usdpath=repr(context.param_value('usd path')), + delegate=repr(delegates_map.get(context.param_value('renderer'), default_delegate)), + doframe=f" '-f', {repr(str(args['frames'][0]))}," if 'frames' in args else '', + do_skip_exists=repr(do_skip_exists), + ) + + invoc = InvocationJob(['python', ':/karmacall.py']) + invoc.set_extra_file('karmacall.py', script) + # else: # TODO: -f there is testing, if succ - make a parameter out of it on the node or smth + # invoc = InvocationJob(['husk', '-R', delegates_map.get(context.param_value('renderer'), default_delegate), '-V', '2a', + # '--make-output-path'] + + # (['-f', str(args['frames'][0])] if 'frames' in args else []) + + # ['-o', context.param_value('image path'), context.param_value('usd path')], + # env=env) res = ProcessingResult(invoc) return res diff --git a/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/common.py b/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/common.py new file mode 100644 index 00000000..9a9049b8 --- /dev/null +++ b/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/common.py @@ -0,0 +1,51 @@ + +def gpu_device_env_common_code(): + return ( + 'import os\n' + 'from lifeblood_connection import get_provided_devices\n' + '\n' + 'def _do_gpu_related_env_setup():\n' + ' provided_devices = get_provided_devices()\n' + ' if "{gpu_dev_type}" not in provided_devices:\n' + ' return\n' + ' enabled_karma_devices_raw = {{dev_tags["karma_dev"] for _, dev_tags in get_provided_devices().get("{gpu_dev_type}", {{}}).items() if "karma_dev" in dev_tags}}\n' + ' opencl_devices_raw = [dev_tags["houdini_ocl"] for _, dev_tags in get_provided_devices().get("{gpu_dev_type}", {{}}).items() if "houdini_ocl" in dev_tags]\n' + ' enabled_karma_devices = set()\n' + ' optix_device_count = 0\n' + ' try:\n' + ' for x in enabled_karma_devices_raw:\n' + ' if "/" in x:\n' + ' x, e = x.split("/")\n' + ' optix_device_count = max(int(x)+1, optix_device_count, int(e))\n' + ' enabled_karma_devices.add(int(x))\n' + ' except ValueError:\n' + ' print("karma_dev tag of gpu device must be an integer! disabling all gpu")\n' + '\n' + ' if len(opencl_devices_raw) == 0 or ":" not in opencl_devices_raw[0]:\n' + ' os.environ["HOUDINI_OCL_DEVICETYPE"] = "CPU"\n' + ' print("no GPU opencl devices enabled")\n' + ' else:\n' + ' ocl_dev_type, ocl_dev_vendor = opencl_devices_raw[0].split(":", 1)\n' + ' ocl_dev_num = None\n' + ' if ":" in ocl_dev_vendor:\n' + ' ocl_dev_vendor, ocl_dev_num = ocl_dev_vendor.rsplit(":", 1)\n' + ' print(f"ocl device type \'{{ocl_dev_type}}\' num \'{{ocl_dev_num}}\' vendor \'{{ocl_dev_vendor}}\' is enabled")\n' + ' os.environ["HOUDINI_OCL_DEVICETYPE"] = ocl_dev_type\n' + ' if ocl_dev_vendor:\n' + ' os.environ["HOUDINI_OCL_VENDOR"] = ocl_dev_vendor\n' + ' if ocl_dev_num:\n' + ' os.environ["HOUDINI_OCL_DEVICENUMBER"] = ocl_dev_num\n' + '\n' + ' if len(enabled_karma_devices) == 0:\n' + ' os.environ["KARMA_XPU_DISABLE_OPTIX_DEVICE"] = "1"\n' + ' print("no karma xpu optix devices enabled")\n' + ' for i in range(optix_device_count):\n' + ' if i in enabled_karma_devices:\n' + ' print(f"karma xpu optix device {{i}} enabled")\n' + ' continue\n' + ' os.environ[f"KARMA_XPU_DISABLE_DEVICE_{{i}}"] = "1"\n' + '\n' + '_do_gpu_related_env_setup()\n' + '\n').format( + gpu_dev_type="gpu", + ) diff --git a/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/rop_base_node.py b/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/rop_base_node.py index 42c10595..3adf8c86 100644 --- a/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/rop_base_node.py +++ b/src/lifeblood/stock_nodes/houdini/python/3/lifeblood_stock_houdini_helpers/rop_base_node.py @@ -3,6 +3,7 @@ from lifeblood.nodethings import ProcessingResult, ProcessingError from lifeblood.invocationjob import InvocationJob, InvocationEnvironment from lifeblood.text import filter_by_pattern +from .common import gpu_device_env_common_code from typing import Iterable, Optional @@ -126,6 +127,7 @@ def process_task(self, context) -> ProcessingResult: spawnlines = '' script = \ + gpu_device_env_common_code() + \ f'import os\n' \ f'import hou\n' \ f'import lifeblood_connection\n' @@ -212,8 +214,14 @@ def process_task(self, context) -> ProcessingResult: script += \ f'print("all done!")\n' - inv = InvocationJob(['hython', ':/work_to_do.py'], env=env) + launch_wrapper_code = ( + gpu_device_env_common_code() + + 'import sys, subprocess\n' + 'sys.exit(subprocess.Popen(sys.argv[1:]).wait())') + + inv = InvocationJob(['python', ':/launch_wrapper.py', 'hython', ':/work_to_do.py'], env=env) inv.set_extra_file('work_to_do.py', script) + inv.set_extra_file('launch_wrapper.py', launch_wrapper_code) res = ProcessingResult(job=inv) return res