def L_asm(self, runtime, visible_label): #eax - pointer to hitpoint structure asm_structs = renmas.utils.structs("hitpoint") ASM = """ #DATA """ ASM += asm_structs + """ float position[4] float spectrum[4] float zero = 0.0 ; temp variables need for shading of light ; later you can try using stack for this, dynamic aligment is required! uint32 ptr_hp #CODE mov dword [ptr_hp], eax ; save pointer to hitpoint macro eq128 xmm0 = position - eax.hitpoint.hit """ ASM += util.normalization("xmm0", "xmm1", "xmm2") + """ macro dot xmm1 = xmm0 * eax.hitpoint.normal macro if xmm1 < zero goto reject macro eq128 eax.hitpoint.wi = xmm0 macro eq32 eax.hitpoint.ndotwi = xmm1 ; test visibility of two points macro eq128 xmm0 = position macro eq128 xmm1 = eax.hitpoint.hit """ ASM += "call " + visible_label + "\n" + """ cmp eax, 1 jne reject mov eax, dword [ptr_hp] macro eq128 eax.hitpoint.spectrum = spectrum mov dword [eax + hitpoint.visible], 1 ret reject: mov eax, dword [ptr_hp] mov dword [eax + hitpoint.visible], 0 ret """ assembler = util.get_asm() mc = assembler.assemble(ASM, True) #mc.print_machine_code() name = "pointlight_L" + str(util.unique()) self.ds = runtime.load(name, mc) self._populate_ds() #FIXME - add method to runtime class so we can ask runtime for address of module self.func_ptr = runtime.modules[name][0]
def visible_asm(runtime, label, ray_scene_isect): # visibility of two points # xmm0 = p1 # xmm1 = p2 norm = util.normalization("xmm1", "xmm2", "xmm3") asm_structs = util.structs("ray", "hitpoint") xmm = "xmm1" tmp1 = "xmm2" line1 = line2 = line3 = "" if util.AVX: line1 = "vdpps " + tmp1 + "," + xmm + "," + xmm + ", 0x7f \n" line2 = "vsqrtps " + tmp1 + "," + tmp1 + "\n" elif util.SSE41: line1 = "movaps " + tmp1 + "," + xmm + "\n" line2 = "dpps " + tmp1 + "," + tmp1 + ", 0x7F\n" line3 = "sqrtps " + tmp1 + "," + tmp1 + "\n" else: line1 = "macro dot " + tmp1 + " = " + xmm + "*" + xmm + "\n" line2 = "macro broadcast " + tmp1 + " = " + tmp1 + "[0]\n" line3 = "sqrtps " + tmp1 + "," + tmp1 + "\n" code = line1 + line2 + line3 ASM = """ #DATA """ ASM += asm_structs + """ hitpoint hp ray r1 float distance float epsilon = 0.0005 #CODE """ ASM += " global " + label + ":\n" + """ macro eq128 xmm1 = xmm1 - xmm0 macro eq128 r1.origin = xmm0 """ ASM += code + """ macro eq32 distance = xmm2 - epsilon {xmm0, xmm1} macro eq128 xmm1 = xmm1 / xmm2 {xmm0, xmm1} macro eq128 r1.dir = xmm1 ; call ray scene intersection mov eax, r1 mov ebx, hp """ ASM += "call " + ray_scene_isect + """ cmp eax, 0 jne _maybe_visible ;no intersection ocure that mean that points are visible mov eax, 1 ret _maybe_visible: macro eq32 xmm0 = distance macro if xmm0 < hp.t goto accept xor eax, eax ret accept: mov eax, 1 ret """ assembler = util.get_asm() mc = assembler.assemble(ASM, True) #mc.print_machine_code() name = "visible" + str(util.unique()) runtime.load(name, mc)
def brdf_asm(self, runtime): #eax pointer to hitpoint name = "oren" + str(hash(self)) util.load_func(runtime, "fast_acos_ps", "fast_sin_ss", "fast_tan_ss") ASM = """ #DATA """ ASM += "float " + name + "spectrum[4] \n" ASM += "float " + name + "k[4] \n" ASM += "float " + name + "zero[4] = 0.0, 0.0, 0.0, 0.0 \n" ASM += "float " + name + "A \n" ASM += "float " + name + "B \n" ASM += "float " + name + "alpha \n" ASM += "float " + name + "beta \n" ASM += "uint32 " + name + "hp_ptr \n" ASM += "#CODE \n" ASM += "mov dword [" + name + "hp_ptr], eax \n" ASM += "macro dot xmm0 = eax.hitpoint.normal * eax.hitpoint.wo \n" ASM += "macro eq32 xmm1 = eax.hitpoint.ndotwi \n" ASM += "movlhps xmm0, xmm1 \n" ASM += "call fast_acos_ps \n" ASM += "movhlps xmm1, xmm0 \n" ASM += "macro eq32 xmm2 = xmm0 \n" ASM += "macro eq32 xmm3 = xmm1 \n" ASM += "minss xmm0, xmm1 \n" # _beta ASM += "maxss xmm2, xmm3 \n" # _alpha ASM += "macro eq32 " + name + "alpha = xmm2 \n" ASM += "call fast_tan_ss \n" ASM += "macro eq32 " + name + "beta = xmm0 \n" ASM += "macro eq32 xmm0 = " + name + "alpha \n" ASM += "call fast_sin_ss \n" ASM += "macro eq32 xmm0 = xmm0 * " + name + "beta \n" ASM += "macro eq32 " + name + "alpha = xmm0 \n" # sin(alpha) * tan(beta) ASM += "mov eax, dword [" + name + "hp_ptr]\n" ASM += "macro dot xmm0 = eax.hitpoint.normal * eax.hitpoint.wo \n" ASM += "macro broadcast xmm0 = xmm0[0] \n" ASM += "macro eq128 xmm0 = xmm0 * eax.hitpoint.normal \n" ASM += "macro eq128 xmm1 = eax.hitpoint.wo \n" ASM += "macro eq128 xmm1 = xmm1 - xmm0 \n" ASM += util.normalization("xmm1", "xmm4", "xmm5") #v1 ASM += "macro eq32 xmm2 = eax.hitpoint.ndotwi \n" ASM += "macro broadcast xmm2 = xmm2[0] \n" ASM += "macro eq128 xmm2 = xmm2 * eax.hitpoint.normal {xmm1} \n" ASM += "macro eq128 xmm3 = eax.hitpoint.wi \n" ASM += "macro eq128 xmm3 = xmm3 - xmm2 {xmm1} \n" ASM += util.normalization("xmm3", "xmm5", "xmm6") #v2 ASM += "macro dot xmm3 = xmm3 * xmm1 \n" ASM += "maxss xmm3, dword [" + name + "zero] \n" ASM += "macro eq32 xmm3 = xmm3 * " + name + "alpha \n" ASM += "macro eq32 xmm3 = xmm3 * " + name + "B \n" ASM += "macro eq32 xmm3 = xmm3 + " + name + "A \n" ASM += "macro broadcast xmm0 = xmm3[0] \n" ASM += "macro eq128 xmm0 = xmm0 * " + name + "spectrum \n" if self.k is not None: ASM += "macro eq128 xmm0 = xmm0 * " + name + "k\n" return ASM
def L_asm(self, runtime, visible_label): self.shape.light_sample_asm(runtime) #eax - pointer to hitpoint structure asm_structs = renmas.utils.structs("hitpoint") ASM = """ #DATA """ ASM += asm_structs + """ float spectrum[4] float minus_one[4] = -1.0, -1.0, -1.0, 0.0 float tmp_spectrum[4] = 0.0, 0.0, 0.0, 0.0 float zero = 0.0 uint32 ptr_sample ; temp variables need for shading of light ; later you can try using stack for this, dynamic aligment is required! uint32 ptr_hp #CODE mov dword [ptr_hp], eax ; save pointer to hitpoint call dword [ptr_sample] mov eax, dword [ptr_hp] macro eq128 xmm0 = eax.hitpoint.light_sample - eax.hitpoint.hit macro dot xmm4 = xmm0 * xmm0 """ ASM += util.normalization("xmm0", "xmm1", "xmm2") + """ macro eq128 xmm5 = xmm0 * minus_one {xmm4} macro dot xmm6 = xmm5 * eax.hitpoint.light_normal {xmm0, xmm4} macro eq128 xmm7 = spectrum {xmm0} macro eq32 xmm4 = xmm4 * eax.hitpoint.light_pdf {xmm0} macro eq32 xmm6 = xmm6 / xmm4 {xmm0} macro broadcast xmm6 = xmm6[0] macro eq128 xmm7 = xmm7 * xmm6 macro eq128 tmp_spectrum = xmm7 macro dot xmm1 = xmm0 * eax.hitpoint.normal macro if xmm1 < zero goto reject macro eq128 eax.hitpoint.wi = xmm0 macro eq32 eax.hitpoint.ndotwi = xmm1 ; test visibility of two points macro eq128 xmm0 = eax.hitpoint.light_sample macro eq128 xmm1 = eax.hitpoint.hit """ ASM += "call " + visible_label + "\n" + """ cmp eax, 1 jne reject mov eax, dword [ptr_hp] macro eq128 eax.hitpoint.spectrum = tmp_spectrum mov dword [eax + hitpoint.visible], 1 ret reject: mov eax, dword [ptr_hp] mov dword [eax + hitpoint.visible], 0 ret """ assembler = util.get_asm() mc = assembler.assemble(ASM, True) #mc.print_machine_code() name = "arealight_L" + str(util.unique()) self.ds = runtime.load(name, mc) self._populate_ds() #FIXME - add method to runtime class so we can ask runtime for address of module self.func_ptr = runtime.modules[name][0]
def get_sample_asm(self, runtime): # eax - pointer to hitpoint asm_structs = renmas.utils.structs("hitpoint") util.load_func(runtime, "random") util.load_func(runtime, "fast_sincos_ps") if util.AVX: line1 = "vmovss xmm1, dword [ecx + 4*ebx] \n" else: line1 = "movss xmm1, dword [ecx + 4*ebx] \n" ASM = """ #DATA """ ASM += asm_structs + """ float ie[4] float pi[4] = 3.14159265359, 3.14159265359, 3.14159265359, 3.14159265359 float one[4] = 1.0, 1.0, 1.0, 1.0 float two[4] = 2.0, 2.0, 2.0, 2.0 float tvector[4] = 0.0034, 1.0, 0.0071, 0.0 float pu[4] float pv[4] float pw[4] uint32 ptr_hp uint32 idx = 0 #CODE """ ASM += """ mov dword [ptr_hp], eax sub dword [idx], 1 js _calculate_samples _gen_direction: mov eax, dword [ptr_hp] macro eq128 xmm1 = eax.hitpoint.normal macro eq128 xmm7 = xmm1 macro eq128 xmm0 = tvector """ ASM += util.cross_product("xmm0", "xmm1", "xmm2", "xmm3") ASM += util.normalization("xmm0", "xmm1", "xmm2") + """ macro eq128 xmm1 = xmm7 macro eq128 xmm6 = xmm0 """ ASM += util.cross_product("xmm0", "xmm1", "xmm2", "xmm3") ASM += """ mov ebx, dword [idx] mov ecx, pu ; in line we load pu, pv or pw """ ASM += line1 + """ macro broadcast xmm1 = xmm1[0] macro eq128 xmm0 = xmm0 * xmm1 {xmm6, xmm7} mov ecx, pv """ ASM += line1 + """ macro broadcast xmm1 = xmm1[0] macro eq128 xmm6 = xmm6 * xmm1 {xmm0, xmm7} macro eq128 xmm0 = xmm0 + xmm6 mov ecx, pw """ ASM += line1 + """ macro broadcast xmm1 = xmm1[0] macro eq128 xmm1 = xmm1 * xmm7 {xmm0} macro eq128 xmm0 = xmm0 + xmm1 {xmm7} """ ASM += util.normalization("xmm0", "xmm1", "xmm2") + """ macro eq128 eax.hitpoint.wi = xmm0 macro dot xmm0 = xmm0 * xmm7 macro eq32 eax.hitpoint.ndotwi = xmm0 ret _calculate_samples: call random """ if self.e == 1: if util.AVX: ASM += "vsqrtps xmm0, xmm0 \n" else: ASM += "sqrtps xmm0, xmm0 \n" else: util.load_func(runtime, "fast_pow_ps") ASM += "macro eq128 xmm1 = ie \n" ASM += "call fast_pow_ps \n" ASM += """ macro eq128 pw = xmm0 macro eq128 xmm0 = xmm0 * xmm0 macro eq128 xmm1 = one - xmm0 """ if util.AVX: ASM += "vsqrtps xmm0, xmm1 \n" else: ASM += "sqrtps xmm0, xmm1 \n" ASM += """ macro eq128 pu = xmm0 macro eq128 pv = xmm0 call random macro eq128 xmm0 = xmm0 * pi macro eq128 xmm0 = xmm0 * two call fast_sincos_ps macro eq128 xmm0 = xmm0 * pv {xmm6} macro eq128 xmm6 = xmm6 * pu {xmm0} macro eq128 pv = xmm0 macro eq128 pu = xmm6 mov dword [idx], 3 jmp _gen_direction """ assembler = util.get_asm() mc = assembler.assemble(ASM, True) #mc.print_machine_code() name = "brdf_hemisphere" + str(util.unique()) self.ds = runtime.load(name, mc) self.ds["ie"] = (self.ie, self.ie, self.ie, self.ie) #FIXME - add method to runtime class so we can ask runtime for address of module self.func_ptr = runtime.modules[name][0]
from tdasm import Runtime import renmas import renmas.maths import renmas.utils as util ASM = """ #DATA float v1[4] = 2.2, 3.3, 4.4, 0.0 #CODE movaps xmm0, oword [v1] """ code = util.normalization("xmm0", "xmm1", "xmm2") ASM += code + """ movaps oword [v1], xmm0 """ if __name__ == "__main__": print(ASM) asm = util.get_asm() mc = asm.assemble(ASM) runtime = Runtime() ds = runtime.load("test", mc) runtime.run("test") print(ds["v1"]) v = renmas.maths.Vector3(2.2, 3.3, 4.4) v.normalize()
def brdf_asm(self, runtime): # eax pointer to hitpoint name = "CookTorr" + str(hash(self)) ASM = """ #DATA """ ASM += "float " + name + "spectrum[4] \n" ASM += "float " + name + "k[4] \n" ASM += "float " + name + "h[4] \n" ASM += "uint32 " + name + "hp_ptr \n" ASM += "float " + name + "one[4] = 1.0, 1.0, 1.0, 0.0 \n" ASM += "float " + name + "two = 2.0 \n" ASM += "float " + name + "D \n" ASM += "float " + name + "G \n" ASM += "float " + name + "pi = 3.141592653589 \n" ASM += "#CODE \n" ASM += "mov dword [" + name + "hp_ptr], eax \n" ASM += "macro eq128 xmm0 = eax.hitpoint.wo + eax.hitpoint.wi \n" ASM += util.normalization("xmm0", "xmm1", "xmm2") ASM += "macro eq128 " + name + "h = xmm0 \n" ASM += "mov ebx, " + name + "h \n" ASM += self.dist.D_asm(runtime) ASM += "macro eq32 " + name + "D = xmm0 \n" ASM += "mov eax, dword [" + name + "hp_ptr]\n" ASM += "macro dot xmm0 = eax.hitpoint.normal * " + name + "h \n" ASM += "macro dot xmm1 = eax.hitpoint.normal * eax.hitpoint.wo {xmm0} \n" ASM += "macro dot xmm2 = eax.hitpoint.wo * " + name + "h {xmm0, xmm1} \n" ASM += "macro dot xmm3 = eax.hitpoint.normal * eax.hitpoint.wi {xmm0, xmm1, xmm2} \n" ASM += "macro eq32 xmm4 = " + name + "one \n" ASM += "macro eq32 xmm4 = xmm4 / xmm2 \n" ASM += "macro eq32 xmm5 = " + name + "two \n" ASM += "macro eq32 xmm5 = xmm5 * xmm0 \n" ASM += "macro eq32 xmm6 = xmm5 \n" ASM += "macro eq32 xmm6 = xmm6 * xmm1 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm3 \n" ASM += "macro eq32 xmm6 = xmm6 * xmm4 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm4 \n" ASM += "minss xmm6, dword [" + name + "one] \n" ASM += "minss xmm6, xmm5 \n" ASM += "macro eq32 " + name + "G = xmm6 \n" ASM += "macro eq32 xmm4 = " + name + "one \n" ASM += "macro eq32 xmm4 = xmm4 - xmm3 \n" ASM += "macro eq32 xmm5 = xmm4 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm5 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm5 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm4 \n" ASM += "macro broadcast xmm5 = xmm5[0] \n" ASM += "macro eq128 xmm6 = " + name + "one \n" ASM += "macro eq128 xmm6 = xmm6 - " + name + "spectrum \n" ASM += "macro eq128 xmm6 = xmm6 * xmm5 \n" # F is in xmm6 ASM += "macro eq128 xmm6 = xmm6 + " + name + "spectrum \n" ASM += "macro eq32 xmm3 = xmm3 * xmm1 \n" ASM += "macro eq32 xmm3 = xmm3 * " + name + "pi \n" ASM += "macro eq32 xmm7 = " + name + "D \n" ASM += "macro eq32 xmm7 = xmm7 * " + name + "G \n" ASM += "macro eq32 xmm7 = xmm7 / xmm3 \n" ASM += "macro broadcast xmm0 = xmm7[0] \n" ASM += "macro eq128 xmm0 = xmm0 * xmm6 \n" if self.k is not None: ASM += "macro eq128 xmm0 = xmm0 * " + name + "k\n" return ASM
def brdf_asm(self, runtime): #eax pointer to hitpoint name = "CookTorr" + str(hash(self)) ASM = """ #DATA """ ASM += "float " + name + "spectrum[4] \n" ASM += "float " + name + "k[4] \n" ASM += "float " + name + "h[4] \n" ASM += "uint32 " + name + "hp_ptr \n" ASM += "float " + name + "one[4] = 1.0, 1.0, 1.0, 0.0 \n" ASM += "float " + name + "two = 2.0 \n" ASM += "float " + name + "D \n" ASM += "float " + name + "G \n" ASM += "float " + name + "pi = 3.141592653589 \n" ASM += "#CODE \n" ASM += "mov dword [" + name + "hp_ptr], eax \n" ASM += "macro eq128 xmm0 = eax.hitpoint.wo + eax.hitpoint.wi \n" ASM += util.normalization("xmm0", "xmm1", "xmm2") ASM += "macro eq128 " + name + "h = xmm0 \n" ASM += "mov ebx, " + name + "h \n" ASM += self.dist.D_asm(runtime) ASM += "macro eq32 " + name + "D = xmm0 \n" ASM += "mov eax, dword [" + name + "hp_ptr]\n" ASM += "macro dot xmm0 = eax.hitpoint.normal * " + name + "h \n" ASM += "macro dot xmm1 = eax.hitpoint.normal * eax.hitpoint.wo {xmm0} \n" ASM += "macro dot xmm2 = eax.hitpoint.wo * " + name + "h {xmm0, xmm1} \n" ASM += "macro dot xmm3 = eax.hitpoint.normal * eax.hitpoint.wi {xmm0, xmm1, xmm2} \n" ASM += "macro eq32 xmm4 = " + name + "one \n" ASM += "macro eq32 xmm4 = xmm4 / xmm2 \n" ASM += "macro eq32 xmm5 = " + name + "two \n" ASM += "macro eq32 xmm5 = xmm5 * xmm0 \n" ASM += "macro eq32 xmm6 = xmm5 \n" ASM += "macro eq32 xmm6 = xmm6 * xmm1 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm3 \n" ASM += "macro eq32 xmm6 = xmm6 * xmm4 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm4 \n" ASM += "minss xmm6, dword [" + name + "one] \n" ASM += "minss xmm6, xmm5 \n" ASM += "macro eq32 " + name + "G = xmm6 \n" ASM += "macro eq32 xmm4 = " + name + "one \n" ASM += "macro eq32 xmm4 = xmm4 - xmm3 \n" ASM += "macro eq32 xmm5 = xmm4 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm5 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm5 \n" ASM += "macro eq32 xmm5 = xmm5 * xmm4 \n" ASM += "macro broadcast xmm5 = xmm5[0] \n" ASM += "macro eq128 xmm6 = " + name + "one \n" ASM += "macro eq128 xmm6 = xmm6 - " + name + "spectrum \n" ASM += "macro eq128 xmm6 = xmm6 * xmm5 \n" #F is in xmm6 ASM += "macro eq128 xmm6 = xmm6 + " + name + "spectrum \n" ASM += "macro eq32 xmm3 = xmm3 * xmm1 \n" ASM += "macro eq32 xmm3 = xmm3 * " + name + "pi \n" ASM += "macro eq32 xmm7 = " + name + "D \n" ASM += "macro eq32 xmm7 = xmm7 * " + name + "G \n" ASM += "macro eq32 xmm7 = xmm7 / xmm3 \n" ASM += "macro broadcast xmm0 = xmm7[0] \n" ASM += "macro eq128 xmm0 = xmm0 * xmm6 \n" if self.k is not None: ASM += "macro eq128 xmm0 = xmm0 * " + name + "k\n" return ASM