aboutsummaryrefslogtreecommitdiff
path: root/pkg/proto/vol/src/pv_gmem.x
blob: 646baf47c7046eae563c16e57966b388039f0489 (plain) (blame)
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
include <imhdr.h>

# PV_GMEM -- Determine how much memory we can get and actually use for the
# volume rotation sequence.  We only allocate actual memory temporarily in
# order to see how much is really available; IMIO will later take care of
# the actual io buffer allocation.

define	DECR_MEM		0.8	# decrement mem by magic factor


procedure pv_gmem (im1, im2, use_both, verbose, max_ws, len_x, oldsize)
pointer	im1			# Input 3d image.
pointer	im2			# Output projected image(s)
bool	use_both		# Use both opacity and intensity voxels
int	verbose			# Report memory usage?
int	max_ws			# Maximum working set to allocate
int	len_x			# (output) safe amount of memory to use
int	oldsize			# (output) old memory to be reset at termination

int	intype, outtype, reqmem, gotmem, needmem, maxsize
int	yzslice_pix, yzreq
pointer	buf_in
bool	topped_out

int	begmem(), sizeof()
errchk	begmem(), malloc()

begin
	# See how much memory we can get; if we cannot get whole input image
	# into memory, do it in chunks of yz slices.
	intype = IM_PIXTYPE(im1)
	outtype = IM_PIXTYPE(im2)
	reqmem = IM_LEN(im1,1) * IM_LEN(im1,2) * IM_LEN(im1,3)
	reqmem = reqmem * sizeof (intype)
	if (use_both)
	    reqmem = 2 * reqmem

	# Add output buffer.
	reqmem = reqmem + IM_LEN(im2,1) * sizeof (outtype)

	# Decrease to max_ws (a task parameter in CHAR units).
	reqmem = min (reqmem, max_ws)

	repeat {
	    iferr (gotmem = begmem (reqmem, oldsize, maxsize)) {
		reqmem = reqmem * DECR_MEM
		if (verbose == YES) {
		    call eprintf ("ERR gotmem=begmem(); retrying at size %d\n")
			call pargi (reqmem)
		}
	    } else {
		if (verbose == YES) {
		    call eprintf ("gotmem=%d, oldsize=%d, maxsize=%d\n")
		    call pargi (gotmem)
		    call pargi (oldsize)
		    call pargi (maxsize)
		}
		break
	    }
	}
	
	# Make sure it is really available, and if not, decrement to largest
	# number of yz slices possible.
	needmem = gotmem
	yzslice_pix = IM_LEN(im1,2) * IM_LEN(im1,3)
	yzreq = yzslice_pix * sizeof(intype)
	if (yzreq - IM_LEN(im1,1) * sizeof(TY_REAL) > needmem) {
	    call eprintf ("Not enough memory for 1 yz slice of input image\n")
	    call error (0, "Out of memory")
	}
	topped_out = false
	repeat {
	    iferr (call malloc (buf_in, needmem, intype)) {
		needmem = needmem - yzreq
		if (needmem < yzreq) {
		    call eprintf ("Had to decrease memory too much")
		    call error (0, "Memory allocation error (yzslice_pix)")
		}
		topped_out = true
	    } else {
		call mfree (buf_in, intype)
		break
	    }
	}

	# Experiments show that horrible things happen if we actually use
	# this much memory.  Decrease by magic factor.
	if (topped_out) {
	    call fixmem (max (needmem, oldsize))
	    if (verbose == YES) {
		call eprintf ("Had to decrease memory for malloc().")
		call eprintf ("  Working set now %d\n")
		    call pargi (needmem)
	    }
	    needmem = needmem * DECR_MEM
	    if (verbose == YES) {
		call eprintf ("Remaining memory for image buffers = %d\n")
		    call pargi (needmem)
	    }
	}
	if (needmem < yzreq) {
	    call eprintf ("Not enough memory for 1 yz slice of input image\n")
	    call error (0, "Out of memory")
	}

	# We return the number of columns to gulp from the input image at one
	# time and oldmem so the task can release its memory on completion.
	len_x = needmem / yzreq
end