How imf_disp connects to mental ray and how to connect to a running instance of mental ray

December 4th, 2006 by Kim Aldis - Viewed 10463 times -




You’ve probably noticed, when mental ray starts rendering a frame, that it’s image file appears almost immediately but that it’s only 128 bytes long. mental images call this a “stub” and it contains information about the frame being rendered. It’s also a text file so the information is easy to grab. Check out the contents using a text editor:

ray3.3,720,486,Skychum,1749,1.000000,6856,1750

And we see a list of 8 comma-delimited values:-

  1. mental ray version
  2. x resolution
  3. y resolution
  4. master hostname (name of machine that initiated the render. remember, this could be a distributed render)
  5. socket ID
  6. gamma value
  7. mental ray PID
  8. 2nd socket ID, floating point framebuffer access (undocumented)

Using this information we can check to see if the mental ray on the other end is still rendering by simply trying to read on the socket ID. If we get something back – anything, it doesn’t matter – mental ray is still alive and well on the other end. If we don’t then it’s dead.

The simplest way to check is simply to telnet the host on the socket ID. In our example above:

telnet skychum 1749

If mental ray is alive we get a connection and a bunch of garbage – the image data. If it’s dead we get a refused connection. Easy as that.

Obviously, if we’re checking renders we don’t want to go through a whole bunch of files doing this all by hand, we want to automate the process. First time I did this I used Perl to open and read on the socket ID but now we have Python, which has more useful modules than cats have hairs, the whole process becomes much simpler and we can use it’s Telnet module. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from win32com.client import constants
import os
import telnetlib
 
siWarning = 4
 
def Scan(sFile):
    Application.LogMessage("Checking : " + sFile)
    iSize = os.path.getsize(sFile)
 
    if (iSize > 128) : # only check 128 byte files.
        Application.LogMessage("File Probably Rendered")
    else:
        # Open and read just the first line
        #
        input = open(sFile, "r")
 
        # split into array
        #
        values = input.readline().split(",")
 
        # and pull out the useful information
        #
        mrVersion = values[0]
        xRes = values[1]
        yRes = values[2]
        hostname = values[3]
        portNum = values[4]
        input.close()
 
        # use telnet to attempt a connection to portNum on hostname
        # If the connection fails then so has the render on the other end
        # 
        try :
            tn = telnetlib.Telnet(hostname, portNum)
            Application.LogMessage("%s: rendering on node %s res = [%s,%s], mr version [%s]" % (sFile, hostname, xRes,yRes, mrVersion))
            tn.close()
        except :
            Application.LogMessage("%s: rendering failed on node %s" % (sFile, hostname), siWarning)
 
def test():
    t = Scan("//Skychum/Jobs/Examples/Render_Pictures/CubelyLoop.1.bmp")
 
test()

Of course, we’re not reading any of the image data that follows, just checking to see if everything is ok. But it’s possible to do this if you wanted, for example, to show rendering progress, either as image, progress bar or even text percentage in an application of your own it’s not hard, you just continue to read and parse the data as it comes in. The details are beyond where I wanted to go with this article but are documented in “Programming mental ray”, an extract of which can be found on that most excellent of resources, Lamrug (http://www.lamrug.org/resources/stubtips.html).

One Response to “How imf_disp connects to mental ray and how to connect to a running instance of mental ray”

  1. Todd Akita says:

    Kim – excellent article. Very handy stuff.

    I did notice that the port number mental ray uses *changes*. Meaning the port used for rendering seems to get rotated around between when you launch/exit XSI.

    Would this work if you had more than 1 render running on the same machine? E.G. would 2 renders running on the same machine (different cpus) be able to sidestep each other using this method?

    -T