Thread: [Algorithms] Filtering
Brought to you by:
vexxed72
From: Andreas B. <and...@gm...> - 2010-10-01 07:57:19
|
Hi, I have a texture in which I use the R, G and B channel to store a value in the [0, 1] range with very high precision. The value is extracted like this in the (Cg) shader: float extractValue(float2 pos) { float4 temp = tex2D(buffer, pos); return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * (1.0 / 16777215.0); } I now want to sample this value with bilinear filtering but when I do this I don't get a correct result. If I do the filtering manually like this: float sampleValue(float2 pos) { float2 ipos = floor(pos); float2 fracs = pos - ipos; float d0 = extractValue(ipos); float d1 = extractValue(ipos + float2(1, 0)); float d2 = extractValue(ipos + float2(0, 1)); float d3 = extractValue(ipos + float2(1, 1)); return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), fracs.y); } everything works as expected. The values in the buffer can be seen as a linear combination of three constants: value = (C0 * r + C1 * g + C2 * b) If we use the built in texture filtering we should get the following if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, b1}. For simplicity we just look at filtering along one axis: filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + lerp(b0, b1, t) * C2; Doing the filtering manually: filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + b1 * C2, t) = = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * C0 + g1 * C1 + b1 * C2) * t = = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = = lerp(r0, r1, t) * C0 + ... So in the world of non floating point numbers these two should be equivalent right? My theory is that the error is caused by an unfortunate order of floating point operations. I've tried variations like: (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + temp.z * (255.0/16777215.0)) and (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / 16777215.0) but all exhibit the same problem. What do you think; is it possible to solve this problem? Regards Andreas |
From: Stefan S. <kef...@gm...> - 2010-10-01 08:45:44
|
Assuming you're after precision, what's wrong with doing it manually? :) If performance is what you're after, and you're working on textures as they were intended(ie, game textures or video or something like that, not 'data'), you could separate contrast & color separately, keeping high contrast resolution, and downsampled color, and you'd save both bandwidth and instr. If you simply want to know 'why', I'm guessing loss of precision in the tex units? You've already ruled out shader precision from your own manual filtering, so doesn't leave much else, imo.. Other than manipulating the data you're working on, which is the only thing you -can- change I guess, I cant really see a solution, but far greater minds linger here than mine, so hold on for what I assume will be a lengthy description of floating point math as it is implemented in modern gpu's :) On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck <and...@gm...>wrote: > Hi, > > I have a texture in which I use the R, G and B channel to store a > value in the [0, 1] range with very high precision. The value is > extracted like this in the (Cg) shader: > > float > extractValue(float2 pos) { > float4 temp = tex2D(buffer, pos); > return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * > (1.0 / 16777215.0); > } > > I now want to sample this value with bilinear filtering but when I do > this I don't get a correct result. If I do the filtering manually like > this: > > float > sampleValue(float2 pos) { > float2 ipos = floor(pos); > float2 fracs = pos - ipos; > float d0 = extractValue(ipos); > float d1 = extractValue(ipos + float2(1, 0)); > float d2 = extractValue(ipos + float2(0, 1)); > float d3 = extractValue(ipos + float2(1, 1)); > return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), fracs.y); > } > > everything works as expected. The values in the buffer can be seen as > a linear combination of three constants: > > value = (C0 * r + C1 * g + C2 * b) > > If we use the built in texture filtering we should get the following > if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, > b1}. For simplicity we just look at filtering along one axis: > > filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + > lerp(b0, b1, t) * C2; > > Doing the filtering manually: > > filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + > b1 * C2, t) = > = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * > C0 + g1 * C1 + b1 * C2) * t = > = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = > = lerp(r0, r1, t) * C0 + ... > > So in the world of non floating point numbers these two should be > equivalent right? > > My theory is that the error is caused by an unfortunate order of > floating point operations. I've tried variations like: > > (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + > temp.z * (255.0/16777215.0)) > > and > > (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / 16777215.0) > > but all exhibit the same problem. What do you think; is it possible to > solve this problem? > > Regards Andreas > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > |
From: Jeff R. <je...@8m...> - 2010-10-01 15:08:42
|
I wouldn't be surprised if the hardware filtering of 8-bit components operated at less than 32 bit precision, at least on some cards. Also worth mentioning that the order of your floating point operations is probably being aggressively modified by your shader compiler in its attempts to optimize. Those last two bits of code you included are probably compiling into the same result. On Fri, Oct 1, 2010 at 3:45 AM, Stefan Sandberg <kef...@gm...>wrote: > Assuming you're after precision, what's wrong with doing it manually? :) > If performance is what you're after, and you're working on textures as they > were intended(ie, game textures or video or something like that, not > 'data'), you could separate contrast & color separately, keeping high > contrast resolution, and downsampled color, and > you'd save both bandwidth and instr. > If you simply want to know 'why', I'm guessing loss of precision in the tex > units? > You've already ruled out shader precision from your own manual filtering, > so doesn't leave much else, imo.. > Other than manipulating the data you're working on, which is the only thing > you -can- change I guess, I cant really see a solution, > but far greater minds linger here than mine, so hold on for what I assume > will be a lengthy description of floating point math as > it is implemented in modern gpu's :) > > > > On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck <and...@gm...>wrote: > >> Hi, >> >> I have a texture in which I use the R, G and B channel to store a >> value in the [0, 1] range with very high precision. The value is >> extracted like this in the (Cg) shader: >> >> float >> extractValue(float2 pos) { >> float4 temp = tex2D(buffer, pos); >> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >> (1.0 / 16777215.0); >> } >> >> I now want to sample this value with bilinear filtering but when I do >> this I don't get a correct result. If I do the filtering manually like >> this: >> >> float >> sampleValue(float2 pos) { >> float2 ipos = floor(pos); >> float2 fracs = pos - ipos; >> float d0 = extractValue(ipos); >> float d1 = extractValue(ipos + float2(1, 0)); >> float d2 = extractValue(ipos + float2(0, 1)); >> float d3 = extractValue(ipos + float2(1, 1)); >> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), fracs.y); >> } >> >> everything works as expected. The values in the buffer can be seen as >> a linear combination of three constants: >> >> value = (C0 * r + C1 * g + C2 * b) >> >> If we use the built in texture filtering we should get the following >> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >> b1}. For simplicity we just look at filtering along one axis: >> >> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >> lerp(b0, b1, t) * C2; >> >> Doing the filtering manually: >> >> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + >> b1 * C2, t) = >> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >> C0 + g1 * C1 + b1 * C2) * t = >> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >> = lerp(r0, r1, t) * C0 + ... >> >> So in the world of non floating point numbers these two should be >> equivalent right? >> >> My theory is that the error is caused by an unfortunate order of >> floating point operations. I've tried variations like: >> >> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >> temp.z * (255.0/16777215.0)) >> >> and >> >> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >> 16777215.0) >> >> but all exhibit the same problem. What do you think; is it possible to >> solve this problem? >> >> Regards Andreas >> >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> > > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > -- Jeff Russell Engineer, 8monkey Labs www.8monkeylabs.com |
From: Michael B. <mi...@fa...> - 2010-10-01 15:21:17
|
You guessed right. The loss of precision is in the texture units. Unfortunately, 8 bit components are filtered to 8 bit results (even though they show up as floating point values in the shader). This is true for nvidia gpus for sure and probably all other gpus. -mike ----- Original Message ----- From: Stefan Sandberg To: Game Development Algorithms Sent: Friday, October 01, 2010 1:45 AM Subject: Re: [Algorithms] Filtering Assuming you're after precision, what's wrong with doing it manually? :) If performance is what you're after, and you're working on textures as they were intended(ie, game textures or video or something like that, not 'data'), you could separate contrast & color separately, keeping high contrast resolution, and downsampled color, and you'd save both bandwidth and instr. If you simply want to know 'why', I'm guessing loss of precision in the tex units? You've already ruled out shader precision from your own manual filtering, so doesn't leave much else, imo.. Other than manipulating the data you're working on, which is the only thing you -can- change I guess, I cant really see a solution, but far greater minds linger here than mine, so hold on for what I assume will be a lengthy description of floating point math as it is implemented in modern gpu's :) On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck <and...@gm...> wrote: Hi, I have a texture in which I use the R, G and B channel to store a value in the [0, 1] range with very high precision. The value is extracted like this in the (Cg) shader: float extractValue(float2 pos) { float4 temp = tex2D(buffer, pos); return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * (1.0 / 16777215.0); } I now want to sample this value with bilinear filtering but when I do this I don't get a correct result. If I do the filtering manually like this: float sampleValue(float2 pos) { float2 ipos = floor(pos); float2 fracs = pos - ipos; float d0 = extractValue(ipos); float d1 = extractValue(ipos + float2(1, 0)); float d2 = extractValue(ipos + float2(0, 1)); float d3 = extractValue(ipos + float2(1, 1)); return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), fracs.y); } everything works as expected. The values in the buffer can be seen as a linear combination of three constants: value = (C0 * r + C1 * g + C2 * b) If we use the built in texture filtering we should get the following if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, b1}. For simplicity we just look at filtering along one axis: filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + lerp(b0, b1, t) * C2; Doing the filtering manually: filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + b1 * C2, t) = = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * C0 + g1 * C1 + b1 * C2) * t = = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = = lerp(r0, r1, t) * C0 + ... So in the world of non floating point numbers these two should be equivalent right? My theory is that the error is caused by an unfortunate order of floating point operations. I've tried variations like: (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + temp.z * (255.0/16777215.0)) and (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / 16777215.0) but all exhibit the same problem. What do you think; is it possible to solve this problem? Regards Andreas ------------------------------------------------------------------------------ Start uncovering the many advantages of virtual appliances and start using them to simplify application deployment and accelerate your shift to cloud computing. http://p.sf.net/sfu/novell-sfdev2dev _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ Start uncovering the many advantages of virtual appliances and start using them to simplify application deployment and accelerate your shift to cloud computing. http://p.sf.net/sfu/novell-sfdev2dev ------------------------------------------------------------------------------ _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list |
From: Nathaniel H. <na...@io...> - 2010-10-01 17:59:27
|
Didn't the newer NVIDIA GPUs fix this? > You guessed right. The loss of precision is in the texture units. > Unfortunately, 8 bit components are filtered to 8 bit results (even though > they show up as floating point values in the shader). This is true for > nvidia gpus for sure and probably all other gpus. > > -mike > ----- Original Message ----- > From: Stefan Sandberg > To: Game Development Algorithms > Sent: Friday, October 01, 2010 1:45 AM > Subject: Re: [Algorithms] Filtering > > > Assuming you're after precision, what's wrong with doing it manually? :) > If performance is what you're after, and you're working on textures as > they were intended(ie, game textures or video or something like that, > not 'data'), you could separate contrast & color separately, keeping > high contrast resolution, and downsampled color, and > you'd save both bandwidth and instr. > If you simply want to know 'why', I'm guessing loss of precision in the > tex units? > You've already ruled out shader precision from your own manual > filtering, so doesn't leave much else, imo.. > Other than manipulating the data you're working on, which is the only > thing you -can- change I guess, I cant really see a solution, > but far greater minds linger here than mine, so hold on for what I > assume will be a lengthy description of floating point math as > it is implemented in modern gpu's :) > > > > > > > On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck > <and...@gm...> wrote: > > Hi, > > I have a texture in which I use the R, G and B channel to store a > value in the [0, 1] range with very high precision. The value is > extracted like this in the (Cg) shader: > > float > extractValue(float2 pos) { > float4 temp = tex2D(buffer, pos); > return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * > (1.0 / 16777215.0); > } > > I now want to sample this value with bilinear filtering but when I do > this I don't get a correct result. If I do the filtering manually like > this: > > float > sampleValue(float2 pos) { > float2 ipos = floor(pos); > float2 fracs = pos - ipos; > float d0 = extractValue(ipos); > float d1 = extractValue(ipos + float2(1, 0)); > float d2 = extractValue(ipos + float2(0, 1)); > float d3 = extractValue(ipos + float2(1, 1)); > return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), > fracs.y); > } > > everything works as expected. The values in the buffer can be seen as > a linear combination of three constants: > > value = (C0 * r + C1 * g + C2 * b) > > If we use the built in texture filtering we should get the following > if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, > b1}. For simplicity we just look at filtering along one axis: > > filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + > lerp(b0, b1, t) * C2; > > Doing the filtering manually: > > filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + > b1 * C2, t) = > = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * > C0 + g1 * C1 + b1 * C2) * t = > = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = > = lerp(r0, r1, t) * C0 + ... > > So in the world of non floating point numbers these two should be > equivalent right? > > My theory is that the error is caused by an unfortunate order of > floating point operations. I've tried variations like: > > (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + > temp.z * (255.0/16777215.0)) > > and > > (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / > 16777215.0) > > but all exhibit the same problem. What do you think; is it possible to > solve this problem? > > Regards Andreas > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > > > > > ------------------------------------------------------------------------------ > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > > > ------------------------------------------------------------------------------ > > > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list |
From: Jeff R. <je...@8m...> - 2010-10-01 18:04:59
|
I'm thinking maybe older gpu's did even courser filtering than this - 6-bit or something instead of 8. Maybe this was the recent improvement? On Fri, Oct 1, 2010 at 12:59 PM, Nathaniel Hoffman <na...@io...> wrote: > Didn't the newer NVIDIA GPUs fix this? > > > You guessed right. The loss of precision is in the texture units. > > Unfortunately, 8 bit components are filtered to 8 bit results (even > though > > they show up as floating point values in the shader). This is true for > > nvidia gpus for sure and probably all other gpus. > > > > -mike > > ----- Original Message ----- > > From: Stefan Sandberg > > To: Game Development Algorithms > > Sent: Friday, October 01, 2010 1:45 AM > > Subject: Re: [Algorithms] Filtering > > > > > > Assuming you're after precision, what's wrong with doing it manually? > :) > > If performance is what you're after, and you're working on textures as > > they were intended(ie, game textures or video or something like that, > > not 'data'), you could separate contrast & color separately, keeping > > high contrast resolution, and downsampled color, and > > you'd save both bandwidth and instr. > > If you simply want to know 'why', I'm guessing loss of precision in the > > tex units? > > You've already ruled out shader precision from your own manual > > filtering, so doesn't leave much else, imo.. > > Other than manipulating the data you're working on, which is the only > > thing you -can- change I guess, I cant really see a solution, > > but far greater minds linger here than mine, so hold on for what I > > assume will be a lengthy description of floating point math as > > it is implemented in modern gpu's :) > > > > > > > > > > > > > > On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck > > <and...@gm...> wrote: > > > > Hi, > > > > I have a texture in which I use the R, G and B channel to store a > > value in the [0, 1] range with very high precision. The value is > > extracted like this in the (Cg) shader: > > > > float > > extractValue(float2 pos) { > > float4 temp = tex2D(buffer, pos); > > return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * > > (1.0 / 16777215.0); > > } > > > > I now want to sample this value with bilinear filtering but when I do > > this I don't get a correct result. If I do the filtering manually > like > > this: > > > > float > > sampleValue(float2 pos) { > > float2 ipos = floor(pos); > > float2 fracs = pos - ipos; > > float d0 = extractValue(ipos); > > float d1 = extractValue(ipos + float2(1, 0)); > > float d2 = extractValue(ipos + float2(0, 1)); > > float d3 = extractValue(ipos + float2(1, 1)); > > return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), > > fracs.y); > > } > > > > everything works as expected. The values in the buffer can be seen as > > a linear combination of three constants: > > > > value = (C0 * r + C1 * g + C2 * b) > > > > If we use the built in texture filtering we should get the following > > if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, > > b1}. For simplicity we just look at filtering along one axis: > > > > filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + > > lerp(b0, b1, t) * C2; > > > > Doing the filtering manually: > > > > filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 > + > > b1 * C2, t) = > > = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * > > C0 + g1 * C1 + b1 * C2) * t = > > = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = > > = lerp(r0, r1, t) * C0 + ... > > > > So in the world of non floating point numbers these two should be > > equivalent right? > > > > My theory is that the error is caused by an unfortunate order of > > floating point operations. I've tried variations like: > > > > (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + > > temp.z * (255.0/16777215.0)) > > > > and > > > > (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / > > 16777215.0) > > > > but all exhibit the same problem. What do you think; is it possible > to > > solve this problem? > > > > Regards Andreas > > > > > ------------------------------------------------------------------------------ > > Start uncovering the many advantages of virtual appliances > > and start using them to simplify application deployment and > > accelerate your shift to cloud computing. > > http://p.sf.net/sfu/novell-sfdev2dev > > _______________________________________________ > > GDAlgorithms-list mailing list > > GDA...@li... > > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > > Archives: > > > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > > > > > > > > > > > > ------------------------------------------------------------------------------ > > > > > > > ------------------------------------------------------------------------------ > > Start uncovering the many advantages of virtual appliances > > and start using them to simplify application deployment and > > accelerate your shift to cloud computing. > > http://p.sf.net/sfu/novell-sfdev2dev > > > > > > > ------------------------------------------------------------------------------ > > > > > > _______________________________________________ > > GDAlgorithms-list mailing list > > GDA...@li... > > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > > Archives: > > > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ > > Start uncovering the many advantages of virtual appliances > > and start using them to simplify application deployment and > > accelerate your shift to cloud computing. > > > http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ > > GDAlgorithms-list mailing list > > GDA...@li... > > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > > Archives: > > > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > -- Jeff Russell Engineer, 8monkey Labs www.8monkeylabs.com |
From: Nathaniel H. <na...@io...> - 2010-10-01 18:32:23
|
My impression was that the DX9-generation NVIDIA ones did 8-bit precision filtering on any 8-bit textures or DXT, and even the DX10 ones (GeForce 9XXX etc.) did higher precision. Being stuck in the console time warp, I don't have much hands-on experience with GPU hardware newer than 2006 or so, so I may be wrong. > I'm thinking maybe older gpu's did even courser filtering than this - > 6-bit > or something instead of 8. Maybe this was the recent improvement? > > On Fri, Oct 1, 2010 at 12:59 PM, Nathaniel Hoffman <na...@io...> wrote: > >> Didn't the newer NVIDIA GPUs fix this? >> >> > You guessed right. The loss of precision is in the texture units. >> > Unfortunately, 8 bit components are filtered to 8 bit results (even >> though >> > they show up as floating point values in the shader). This is true for >> > nvidia gpus for sure and probably all other gpus. >> > >> > -mike >> > ----- Original Message ----- >> > From: Stefan Sandberg >> > To: Game Development Algorithms >> > Sent: Friday, October 01, 2010 1:45 AM >> > Subject: Re: [Algorithms] Filtering >> > >> > >> > Assuming you're after precision, what's wrong with doing it >> manually? >> :) >> > If performance is what you're after, and you're working on textures >> as >> > they were intended(ie, game textures or video or something like that, >> > not 'data'), you could separate contrast & color separately, keeping >> > high contrast resolution, and downsampled color, and >> > you'd save both bandwidth and instr. >> > If you simply want to know 'why', I'm guessing loss of precision in >> the >> > tex units? >> > You've already ruled out shader precision from your own manual >> > filtering, so doesn't leave much else, imo.. >> > Other than manipulating the data you're working on, which is the >> only >> > thing you -can- change I guess, I cant really see a solution, >> > but far greater minds linger here than mine, so hold on for what I >> > assume will be a lengthy description of floating point math as >> > it is implemented in modern gpu's :) >> > >> > >> > >> > >> > >> > >> > On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck >> > <and...@gm...> wrote: >> > >> > Hi, >> > >> > I have a texture in which I use the R, G and B channel to store a >> > value in the [0, 1] range with very high precision. The value is >> > extracted like this in the (Cg) shader: >> > >> > float >> > extractValue(float2 pos) { >> > float4 temp = tex2D(buffer, pos); >> > return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * >> 255.0) * >> > (1.0 / 16777215.0); >> > } >> > >> > I now want to sample this value with bilinear filtering but when I >> do >> > this I don't get a correct result. If I do the filtering manually >> like >> > this: >> > >> > float >> > sampleValue(float2 pos) { >> > float2 ipos = floor(pos); >> > float2 fracs = pos - ipos; >> > float d0 = extractValue(ipos); >> > float d1 = extractValue(ipos + float2(1, 0)); >> > float d2 = extractValue(ipos + float2(0, 1)); >> > float d3 = extractValue(ipos + float2(1, 1)); >> > return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), >> > fracs.y); >> > } >> > >> > everything works as expected. The values in the buffer can be seen >> as >> > a linear combination of three constants: >> > >> > value = (C0 * r + C1 * g + C2 * b) >> > >> > If we use the built in texture filtering we should get the >> following >> > if we sample somewhere between two texels: {r0, g0, b0} and {r1, >> g1, >> > b1}. For simplicity we just look at filtering along one axis: >> > >> > filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >> > lerp(b0, b1, t) * C2; >> > >> > Doing the filtering manually: >> > >> > filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * >> C1 >> + >> > b1 * C2, t) = >> > = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 >> * >> > C0 + g1 * C1 + b1 * C2) * t = >> > = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >> > = lerp(r0, r1, t) * C0 + ... >> > >> > So in the world of non floating point numbers these two should be >> > equivalent right? >> > >> > My theory is that the error is caused by an unfortunate order of >> > floating point operations. I've tried variations like: >> > >> > (temp.x * (16711680.0 / 16777215.0) + temp.y * >> (65280.0/16777215.0) + >> > temp.z * (255.0/16777215.0)) >> > >> > and >> > >> > (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >> > 16777215.0) >> > >> > but all exhibit the same problem. What do you think; is it >> possible >> to >> > solve this problem? >> > >> > Regards Andreas >> > >> > >> ------------------------------------------------------------------------------ >> > Start uncovering the many advantages of virtual appliances >> > and start using them to simplify application deployment and >> > accelerate your shift to cloud computing. >> > http://p.sf.net/sfu/novell-sfdev2dev >> > _______________________________________________ >> > GDAlgorithms-list mailing list >> > GDA...@li... >> > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> > Archives: >> > >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> > >> > >> > >> > >> > >> > >> ------------------------------------------------------------------------------ >> > >> > >> > >> ------------------------------------------------------------------------------ >> > Start uncovering the many advantages of virtual appliances >> > and start using them to simplify application deployment and >> > accelerate your shift to cloud computing. >> > http://p.sf.net/sfu/novell-sfdev2dev >> > >> > >> > >> ------------------------------------------------------------------------------ >> > >> > >> > _______________________________________________ >> > GDAlgorithms-list mailing list >> > GDA...@li... >> > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> > Archives: >> > >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ >> > Start uncovering the many advantages of virtual appliances >> > and start using them to simplify application deployment and >> > accelerate your shift to cloud computing. >> > >> http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ >> > GDAlgorithms-list mailing list >> > GDA...@li... >> > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> > Archives: >> > >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> >> >> >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> > > > > -- > Jeff Russell > Engineer, 8monkey Labs > www.8monkeylabs.com > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list |
From: Fabian G. <ry...@gm...> - 2010-10-01 18:53:23
|
On 01.10.2010 11:04, Jeff Russell wrote: > I'm thinking maybe older gpu's did even courser filtering than this - > 6-bit or something instead of 8. Maybe this was the recent improvement? There's the subpixel resolution of texture coordinates going into the filtering unit and there's the actual filtering precision. The former will make blocks appear once you zoom up close enough. For most texture this isn't a problem as you try to keep the texel:pixel ratio close to 1:1 anyway, but I ran into this a while ago on some textures that were mostly gradients. This is extra-annoying on gradient textures since you can't make them too large either - if they're too large, adjacent pixels have the same color value sometimes, which bilinear filtering will expand into a constant stretch in the middle of your gradient - a very visible problem, unfortunately. The actual filtering has been working on at least 8-bit values for quite some time (at least as far back as the GeForce3 / original Radeons, not sure about earlier cards). You may get more precision on newer cards, but it's probably not much more (half-floats or something like that, most likely). These return paths aren't super-wide for a reason - you don't put 128-bit (4x32) buses all over your chip when you can avoid it. (Samplers most likely support returning full 32-bit results, but it will take more than one cycle to transfer results then). |
From: Ola O. <ola...@gm...> - 2010-10-01 18:12:33
|
While we're throwing ideas around, why not try using a float texture and see if it produces the same error? .ola P.S. Hi Andreas :) ----- Original Message ----- From: "Nathaniel Hoffman" <na...@io...> To: "Game Development Algorithms" <gda...@li...> Sent: Friday, October 01, 2010 7:59 PM Subject: Re: [Algorithms] Filtering > Didn't the newer NVIDIA GPUs fix this? > >> You guessed right. The loss of precision is in the texture units. >> Unfortunately, 8 bit components are filtered to 8 bit results (even >> though >> they show up as floating point values in the shader). This is true for >> nvidia gpus for sure and probably all other gpus. >> >> -mike >> ----- Original Message ----- >> From: Stefan Sandberg >> To: Game Development Algorithms >> Sent: Friday, October 01, 2010 1:45 AM >> Subject: Re: [Algorithms] Filtering >> >> >> Assuming you're after precision, what's wrong with doing it manually? >> :) >> If performance is what you're after, and you're working on textures as >> they were intended(ie, game textures or video or something like that, >> not 'data'), you could separate contrast & color separately, keeping >> high contrast resolution, and downsampled color, and >> you'd save both bandwidth and instr. >> If you simply want to know 'why', I'm guessing loss of precision in the >> tex units? >> You've already ruled out shader precision from your own manual >> filtering, so doesn't leave much else, imo.. >> Other than manipulating the data you're working on, which is the only >> thing you -can- change I guess, I cant really see a solution, >> but far greater minds linger here than mine, so hold on for what I >> assume will be a lengthy description of floating point math as >> it is implemented in modern gpu's :) >> >> >> >> >> >> >> On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck >> <and...@gm...> wrote: >> >> Hi, >> >> I have a texture in which I use the R, G and B channel to store a >> value in the [0, 1] range with very high precision. The value is >> extracted like this in the (Cg) shader: >> >> float >> extractValue(float2 pos) { >> float4 temp = tex2D(buffer, pos); >> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >> (1.0 / 16777215.0); >> } >> >> I now want to sample this value with bilinear filtering but when I do >> this I don't get a correct result. If I do the filtering manually >> like >> this: >> >> float >> sampleValue(float2 pos) { >> float2 ipos = floor(pos); >> float2 fracs = pos - ipos; >> float d0 = extractValue(ipos); >> float d1 = extractValue(ipos + float2(1, 0)); >> float d2 = extractValue(ipos + float2(0, 1)); >> float d3 = extractValue(ipos + float2(1, 1)); >> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), >> fracs.y); >> } >> >> everything works as expected. The values in the buffer can be seen as >> a linear combination of three constants: >> >> value = (C0 * r + C1 * g + C2 * b) >> >> If we use the built in texture filtering we should get the following >> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >> b1}. For simplicity we just look at filtering along one axis: >> >> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >> lerp(b0, b1, t) * C2; >> >> Doing the filtering manually: >> >> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 >> + >> b1 * C2, t) = >> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >> C0 + g1 * C1 + b1 * C2) * t = >> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >> = lerp(r0, r1, t) * C0 + ... >> >> So in the world of non floating point numbers these two should be >> equivalent right? >> >> My theory is that the error is caused by an unfortunate order of >> floating point operations. I've tried variations like: >> >> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >> temp.z * (255.0/16777215.0)) >> >> and >> >> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >> 16777215.0) >> >> but all exhibit the same problem. What do you think; is it possible >> to >> solve this problem? >> >> Regards Andreas >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> >> >> >> >> >> ------------------------------------------------------------------------------ >> >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> >> >> ------------------------------------------------------------------------------ >> >> >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list |
From: Andreas B. <and...@gm...> - 2010-10-01 19:51:58
|
Hi Ola, unfortunately the floating point textures on the platform I'm working on don't support bilinear filtering (this is the reason why I stored the value in an RGB-texture to begin with). /Andreas P.S. Got your Ph.D yet? On Fri, Oct 1, 2010 at 8:12 PM, Ola Olsson <ola...@gm...> wrote: > While we're throwing ideas around, why not try using a float texture and see > if it produces the same error? > > .ola > > P.S. > Hi Andreas :) > > ----- Original Message ----- > From: "Nathaniel Hoffman" <na...@io...> > To: "Game Development Algorithms" <gda...@li...> > Sent: Friday, October 01, 2010 7:59 PM > Subject: Re: [Algorithms] Filtering > > >> Didn't the newer NVIDIA GPUs fix this? >> >>> You guessed right. The loss of precision is in the texture units. >>> Unfortunately, 8 bit components are filtered to 8 bit results (even >>> though >>> they show up as floating point values in the shader). This is true for >>> nvidia gpus for sure and probably all other gpus. >>> >>> -mike >>> ----- Original Message ----- >>> From: Stefan Sandberg >>> To: Game Development Algorithms >>> Sent: Friday, October 01, 2010 1:45 AM >>> Subject: Re: [Algorithms] Filtering >>> >>> >>> Assuming you're after precision, what's wrong with doing it manually? >>> :) >>> If performance is what you're after, and you're working on textures as >>> they were intended(ie, game textures or video or something like that, >>> not 'data'), you could separate contrast & color separately, keeping >>> high contrast resolution, and downsampled color, and >>> you'd save both bandwidth and instr. >>> If you simply want to know 'why', I'm guessing loss of precision in the >>> tex units? >>> You've already ruled out shader precision from your own manual >>> filtering, so doesn't leave much else, imo.. >>> Other than manipulating the data you're working on, which is the only >>> thing you -can- change I guess, I cant really see a solution, >>> but far greater minds linger here than mine, so hold on for what I >>> assume will be a lengthy description of floating point math as >>> it is implemented in modern gpu's :) >>> >>> >>> >>> >>> >>> >>> On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck >>> <and...@gm...> wrote: >>> >>> Hi, >>> >>> I have a texture in which I use the R, G and B channel to store a >>> value in the [0, 1] range with very high precision. The value is >>> extracted like this in the (Cg) shader: >>> >>> float >>> extractValue(float2 pos) { >>> float4 temp = tex2D(buffer, pos); >>> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >>> (1.0 / 16777215.0); >>> } >>> >>> I now want to sample this value with bilinear filtering but when I do >>> this I don't get a correct result. If I do the filtering manually >>> like >>> this: >>> >>> float >>> sampleValue(float2 pos) { >>> float2 ipos = floor(pos); >>> float2 fracs = pos - ipos; >>> float d0 = extractValue(ipos); >>> float d1 = extractValue(ipos + float2(1, 0)); >>> float d2 = extractValue(ipos + float2(0, 1)); >>> float d3 = extractValue(ipos + float2(1, 1)); >>> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), >>> fracs.y); >>> } >>> >>> everything works as expected. The values in the buffer can be seen as >>> a linear combination of three constants: >>> >>> value = (C0 * r + C1 * g + C2 * b) >>> >>> If we use the built in texture filtering we should get the following >>> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >>> b1}. For simplicity we just look at filtering along one axis: >>> >>> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >>> lerp(b0, b1, t) * C2; >>> >>> Doing the filtering manually: >>> >>> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 >>> + >>> b1 * C2, t) = >>> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >>> C0 + g1 * C1 + b1 * C2) * t = >>> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >>> = lerp(r0, r1, t) * C0 + ... >>> >>> So in the world of non floating point numbers these two should be >>> equivalent right? >>> >>> My theory is that the error is caused by an unfortunate order of >>> floating point operations. I've tried variations like: >>> >>> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >>> temp.z * (255.0/16777215.0)) >>> >>> and >>> >>> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >>> 16777215.0) >>> >>> but all exhibit the same problem. What do you think; is it possible >>> to >>> solve this problem? >>> >>> Regards Andreas >>> >>> ------------------------------------------------------------------------------ >>> Start uncovering the many advantages of virtual appliances >>> and start using them to simplify application deployment and >>> accelerate your shift to cloud computing. >>> http://p.sf.net/sfu/novell-sfdev2dev >>> _______________________________________________ >>> GDAlgorithms-list mailing list >>> GDA...@li... >>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>> Archives: >>> >>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>> >>> >>> >>> >>> >>> ------------------------------------------------------------------------------ >>> >>> >>> ------------------------------------------------------------------------------ >>> Start uncovering the many advantages of virtual appliances >>> and start using them to simplify application deployment and >>> accelerate your shift to cloud computing. >>> http://p.sf.net/sfu/novell-sfdev2dev >>> >>> >>> ------------------------------------------------------------------------------ >>> >>> >>> _______________________________________________ >>> GDAlgorithms-list mailing list >>> GDA...@li... >>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>> Archives: >>> >>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ >>> Start uncovering the many advantages of virtual appliances >>> and start using them to simplify application deployment and >>> accelerate your shift to cloud computing. >>> http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ >>> GDAlgorithms-list mailing list >>> GDA...@li... >>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>> Archives: >>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> >> >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > |
From: Andreas B. <and...@gm...> - 2010-10-01 19:42:13
|
Well that certainly explains it. I guess I'm stuck with doing the filtering myself then. Thanks anyway guys! On Fri, Oct 1, 2010 at 4:54 PM, Michael Bunnell <mi...@fa...> wrote: > You guessed right. The loss of precision is in the texture units. > Unfortunately, 8 bit components are filtered to 8 bit results (even though > they show up as floating point values in the shader). This is true > for nvidia gpus for sure and probably all other gpus. > > -mike > > ----- Original Message ----- > From: Stefan Sandberg > To: Game Development Algorithms > Sent: Friday, October 01, 2010 1:45 AM > Subject: Re: [Algorithms] Filtering > Assuming you're after precision, what's wrong with doing it manually? :) > If performance is what you're after, and you're working on textures as they > were intended(ie, game textures or video or something like that, not > 'data'), you could separate contrast & color separately, keeping high > contrast resolution, and downsampled color, and > you'd save both bandwidth and instr. > If you simply want to know 'why', I'm guessing loss of precision in the tex > units? > You've already ruled out shader precision from your own manual filtering, > so doesn't leave much else, imo.. > Other than manipulating the data you're working on, which is the only thing > you -can- change I guess, I cant really see a solution, > but far greater minds linger here than mine, so hold on for what I assume > will be a lengthy description of floating point math as > it is implemented in modern gpu's :) > > > On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck <and...@gm...> > wrote: >> >> Hi, >> >> I have a texture in which I use the R, G and B channel to store a >> value in the [0, 1] range with very high precision. The value is >> extracted like this in the (Cg) shader: >> >> float >> extractValue(float2 pos) { >> float4 temp = tex2D(buffer, pos); >> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >> (1.0 / 16777215.0); >> } >> >> I now want to sample this value with bilinear filtering but when I do >> this I don't get a correct result. If I do the filtering manually like >> this: >> >> float >> sampleValue(float2 pos) { >> float2 ipos = floor(pos); >> float2 fracs = pos - ipos; >> float d0 = extractValue(ipos); >> float d1 = extractValue(ipos + float2(1, 0)); >> float d2 = extractValue(ipos + float2(0, 1)); >> float d3 = extractValue(ipos + float2(1, 1)); >> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), fracs.y); >> } >> >> everything works as expected. The values in the buffer can be seen as >> a linear combination of three constants: >> >> value = (C0 * r + C1 * g + C2 * b) >> >> If we use the built in texture filtering we should get the following >> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >> b1}. For simplicity we just look at filtering along one axis: >> >> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >> lerp(b0, b1, t) * C2; >> >> Doing the filtering manually: >> >> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 + >> b1 * C2, t) = >> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >> C0 + g1 * C1 + b1 * C2) * t = >> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >> = lerp(r0, r1, t) * C0 + ... >> >> So in the world of non floating point numbers these two should be >> equivalent right? >> >> My theory is that the error is caused by an unfortunate order of >> floating point operations. I've tried variations like: >> >> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >> temp.z * (255.0/16777215.0)) >> >> and >> >> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >> 16777215.0) >> >> but all exhibit the same problem. What do you think; is it possible to >> solve this problem? >> >> Regards Andreas >> >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > ________________________________ > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > > ________________________________ > > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > |
From: Sylvain G. V. <vi...@ii...> - 2010-10-01 20:02:37
|
> On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck > <and...@gm...> wrote: > filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 > + > b1 * C2, t) = > = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * > C0 + g1 * C1 + b1 * C2) * t = > = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = > = lerp(r0, r1, t) * C0 + ... > > So in the world of non floating point numbers these two should be > equivalent right? No they're not, due to rounding. Take for example 2 texels: R=1 G=0 B=0 and R=0 G=255 B=0 Lerping in the texfetch would spawn something like: R=0 G=128 B=0 Definitely not what you're expecting! You'd want : R=0 G=255 B=something Using texfetch interpolation fails because it doesn't treat the 3 channels as one number; it won't always interpolate in the correct direction (interpreting 128 as either 0,5 or 1,5 depending on what's on the next channel) and it won't alter the other channel accordingly either. |
From: Tibor K. <tib...@gm...> - 2010-10-01 20:42:26
|
Just wanted to point something out - now that you know it won't work it probably makes sense to switch to a float32 texture and still do the filtering manually... you'll at least save the pack/unpack instructions :) - Tibor On 10/1/2010 9:51 PM, Andreas Brinck wrote: > Hi Ola, > > unfortunately the floating point textures on the platform I'm working > on don't support bilinear filtering (this is the reason why I stored > the value in an RGB-texture to begin with). > > /Andreas > > P.S. Got your Ph.D yet? > > On Fri, Oct 1, 2010 at 8:12 PM, Ola Olsson<ola...@gm...> wrote: >> While we're throwing ideas around, why not try using a float texture and see >> if it produces the same error? >> >> .ola >> >> P.S. >> Hi Andreas :) >> >> ----- Original Message ----- >> From: "Nathaniel Hoffman"<na...@io...> >> To: "Game Development Algorithms"<gda...@li...> >> Sent: Friday, October 01, 2010 7:59 PM >> Subject: Re: [Algorithms] Filtering >> >> >>> Didn't the newer NVIDIA GPUs fix this? >>> >>>> You guessed right. The loss of precision is in the texture units. >>>> Unfortunately, 8 bit components are filtered to 8 bit results (even >>>> though >>>> they show up as floating point values in the shader). This is true for >>>> nvidia gpus for sure and probably all other gpus. >>>> >>>> -mike >>>> ----- Original Message ----- >>>> From: Stefan Sandberg >>>> To: Game Development Algorithms >>>> Sent: Friday, October 01, 2010 1:45 AM >>>> Subject: Re: [Algorithms] Filtering >>>> >>>> >>>> Assuming you're after precision, what's wrong with doing it manually? >>>> :) >>>> If performance is what you're after, and you're working on textures as >>>> they were intended(ie, game textures or video or something like that, >>>> not 'data'), you could separate contrast& color separately, keeping >>>> high contrast resolution, and downsampled color, and >>>> you'd save both bandwidth and instr. >>>> If you simply want to know 'why', I'm guessing loss of precision in the >>>> tex units? >>>> You've already ruled out shader precision from your own manual >>>> filtering, so doesn't leave much else, imo.. >>>> Other than manipulating the data you're working on, which is the only >>>> thing you -can- change I guess, I cant really see a solution, >>>> but far greater minds linger here than mine, so hold on for what I >>>> assume will be a lengthy description of floating point math as >>>> it is implemented in modern gpu's :) >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck >>>> <and...@gm...> wrote: >>>> >>>> Hi, >>>> >>>> I have a texture in which I use the R, G and B channel to store a >>>> value in the [0, 1] range with very high precision. The value is >>>> extracted like this in the (Cg) shader: >>>> >>>> float >>>> extractValue(float2 pos) { >>>> float4 temp = tex2D(buffer, pos); >>>> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >>>> (1.0 / 16777215.0); >>>> } >>>> >>>> I now want to sample this value with bilinear filtering but when I do >>>> this I don't get a correct result. If I do the filtering manually >>>> like >>>> this: >>>> >>>> float >>>> sampleValue(float2 pos) { >>>> float2 ipos = floor(pos); >>>> float2 fracs = pos - ipos; >>>> float d0 = extractValue(ipos); >>>> float d1 = extractValue(ipos + float2(1, 0)); >>>> float d2 = extractValue(ipos + float2(0, 1)); >>>> float d3 = extractValue(ipos + float2(1, 1)); >>>> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), >>>> fracs.y); >>>> } >>>> >>>> everything works as expected. The values in the buffer can be seen as >>>> a linear combination of three constants: >>>> >>>> value = (C0 * r + C1 * g + C2 * b) >>>> >>>> If we use the built in texture filtering we should get the following >>>> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >>>> b1}. For simplicity we just look at filtering along one axis: >>>> >>>> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >>>> lerp(b0, b1, t) * C2; >>>> >>>> Doing the filtering manually: >>>> >>>> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 >>>> + >>>> b1 * C2, t) = >>>> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >>>> C0 + g1 * C1 + b1 * C2) * t = >>>> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >>>> = lerp(r0, r1, t) * C0 + ... >>>> >>>> So in the world of non floating point numbers these two should be >>>> equivalent right? >>>> >>>> My theory is that the error is caused by an unfortunate order of >>>> floating point operations. I've tried variations like: >>>> >>>> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >>>> temp.z * (255.0/16777215.0)) >>>> >>>> and >>>> >>>> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >>>> 16777215.0) >>>> >>>> but all exhibit the same problem. What do you think; is it possible >>>> to >>>> solve this problem? >>>> >>>> Regards Andreas >>>> >>>> ------------------------------------------------------------------------------ >>>> Start uncovering the many advantages of virtual appliances >>>> and start using them to simplify application deployment and >>>> accelerate your shift to cloud computing. >>>> http://p.sf.net/sfu/novell-sfdev2dev >>>> _______________________________________________ >>>> GDAlgorithms-list mailing list >>>> GDA...@li... >>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>> Archives: >>>> >>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>>> >>>> >>>> >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> Start uncovering the many advantages of virtual appliances >>>> and start using them to simplify application deployment and >>>> accelerate your shift to cloud computing. >>>> http://p.sf.net/sfu/novell-sfdev2dev >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> >>>> >>>> _______________________________________________ >>>> GDAlgorithms-list mailing list >>>> GDA...@li... >>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>> Archives: >>>> >>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ >>>> Start uncovering the many advantages of virtual appliances >>>> and start using them to simplify application deployment and >>>> accelerate your shift to cloud computing. >>>> http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ >>>> GDAlgorithms-list mailing list >>>> GDA...@li... >>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>> Archives: >>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>> >>> >>> ------------------------------------------------------------------------------ >>> Start uncovering the many advantages of virtual appliances >>> and start using them to simplify application deployment and >>> accelerate your shift to cloud computing. >>> http://p.sf.net/sfu/novell-sfdev2dev >>> _______________________________________________ >>> GDAlgorithms-list mailing list >>> GDA...@li... >>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>> Archives: >>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > |
From: Adrian B. <ad...@gm...> - 2010-10-03 01:44:20
|
FYI, DirectX 11 claims: "Require 8-bits of subtexel and sub-mip precision on texture filtering" It doesn't appear to say anything about precision of the resulting color. I would think subtexel precision usefulness would be at least somewhat coupled to output precision, but maybe not. Cheers, Adrian On Fri, Oct 1, 2010 at 1:42 PM, Tibor Klajnscek <tib...@gm...> wrote: > Just wanted to point something out - now that you know it won't work > it probably makes sense to switch to a float32 texture and still do the > filtering manually... you'll at least save the pack/unpack instructions :) > > - Tibor > > On 10/1/2010 9:51 PM, Andreas Brinck wrote: >> Hi Ola, >> >> unfortunately the floating point textures on the platform I'm working >> on don't support bilinear filtering (this is the reason why I stored >> the value in an RGB-texture to begin with). >> >> /Andreas >> >> P.S. Got your Ph.D yet? >> >> On Fri, Oct 1, 2010 at 8:12 PM, Ola Olsson<ola...@gm...> wrote: >>> While we're throwing ideas around, why not try using a float texture and see >>> if it produces the same error? >>> >>> .ola >>> >>> P.S. >>> Hi Andreas :) >>> >>> ----- Original Message ----- >>> From: "Nathaniel Hoffman"<na...@io...> >>> To: "Game Development Algorithms"<gda...@li...> >>> Sent: Friday, October 01, 2010 7:59 PM >>> Subject: Re: [Algorithms] Filtering >>> >>> >>>> Didn't the newer NVIDIA GPUs fix this? >>>> >>>>> You guessed right. The loss of precision is in the texture units. >>>>> Unfortunately, 8 bit components are filtered to 8 bit results (even >>>>> though >>>>> they show up as floating point values in the shader). This is true for >>>>> nvidia gpus for sure and probably all other gpus. >>>>> >>>>> -mike >>>>> ----- Original Message ----- >>>>> From: Stefan Sandberg >>>>> To: Game Development Algorithms >>>>> Sent: Friday, October 01, 2010 1:45 AM >>>>> Subject: Re: [Algorithms] Filtering >>>>> >>>>> >>>>> Assuming you're after precision, what's wrong with doing it manually? >>>>> :) >>>>> If performance is what you're after, and you're working on textures as >>>>> they were intended(ie, game textures or video or something like that, >>>>> not 'data'), you could separate contrast& color separately, keeping >>>>> high contrast resolution, and downsampled color, and >>>>> you'd save both bandwidth and instr. >>>>> If you simply want to know 'why', I'm guessing loss of precision in the >>>>> tex units? >>>>> You've already ruled out shader precision from your own manual >>>>> filtering, so doesn't leave much else, imo.. >>>>> Other than manipulating the data you're working on, which is the only >>>>> thing you -can- change I guess, I cant really see a solution, >>>>> but far greater minds linger here than mine, so hold on for what I >>>>> assume will be a lengthy description of floating point math as >>>>> it is implemented in modern gpu's :) >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Fri, Oct 1, 2010 at 9:57 AM, Andreas Brinck >>>>> <and...@gm...> wrote: >>>>> >>>>> Hi, >>>>> >>>>> I have a texture in which I use the R, G and B channel to store a >>>>> value in the [0, 1] range with very high precision. The value is >>>>> extracted like this in the (Cg) shader: >>>>> >>>>> float >>>>> extractValue(float2 pos) { >>>>> float4 temp = tex2D(buffer, pos); >>>>> return (temp.x * 16711680.0 + temp.y * 65280.0 + temp.z * 255.0) * >>>>> (1.0 / 16777215.0); >>>>> } >>>>> >>>>> I now want to sample this value with bilinear filtering but when I do >>>>> this I don't get a correct result. If I do the filtering manually >>>>> like >>>>> this: >>>>> >>>>> float >>>>> sampleValue(float2 pos) { >>>>> float2 ipos = floor(pos); >>>>> float2 fracs = pos - ipos; >>>>> float d0 = extractValue(ipos); >>>>> float d1 = extractValue(ipos + float2(1, 0)); >>>>> float d2 = extractValue(ipos + float2(0, 1)); >>>>> float d3 = extractValue(ipos + float2(1, 1)); >>>>> return lerp(lerp(d0, d1, fracs.x), lerp(d2, d3, fracs.x), >>>>> fracs.y); >>>>> } >>>>> >>>>> everything works as expected. The values in the buffer can be seen as >>>>> a linear combination of three constants: >>>>> >>>>> value = (C0 * r + C1 * g + C2 * b) >>>>> >>>>> If we use the built in texture filtering we should get the following >>>>> if we sample somewhere between two texels: {r0, g0, b0} and {r1, g1, >>>>> b1}. For simplicity we just look at filtering along one axis: >>>>> >>>>> filtered value = lerp(r0, r1, t) * C0 + lerp(g0, g1, t) * C1 + >>>>> lerp(b0, b1, t) * C2; >>>>> >>>>> Doing the filtering manually: >>>>> >>>>> filtered value = lerp(r0 * C0 + b0 * C1 + g0 * C2, r1 * C0 + g1 * C1 >>>>> + >>>>> b1 * C2, t) = >>>>> = (r0 * C0 + b0 * C1 + g0 * C2) * (1 - t) + (r1 * >>>>> C0 + g1 * C1 + b1 * C2) * t = >>>>> = (r0 * C0) * (1 - t) + (r1 * C0) * t + ... = >>>>> = lerp(r0, r1, t) * C0 + ... >>>>> >>>>> So in the world of non floating point numbers these two should be >>>>> equivalent right? >>>>> >>>>> My theory is that the error is caused by an unfortunate order of >>>>> floating point operations. I've tried variations like: >>>>> >>>>> (temp.x * (16711680.0 / 16777215.0) + temp.y * (65280.0/16777215.0) + >>>>> temp.z * (255.0/16777215.0)) >>>>> >>>>> and >>>>> >>>>> (((temp.x * 256.0 + temp.y) * 256.0 + temp.z) * 255.0) * (1.0 / >>>>> 16777215.0) >>>>> >>>>> but all exhibit the same problem. What do you think; is it possible >>>>> to >>>>> solve this problem? >>>>> >>>>> Regards Andreas >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> Start uncovering the many advantages of virtual appliances >>>>> and start using them to simplify application deployment and >>>>> accelerate your shift to cloud computing. >>>>> http://p.sf.net/sfu/novell-sfdev2dev >>>>> _______________________________________________ >>>>> GDAlgorithms-list mailing list >>>>> GDA...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>>> Archives: >>>>> >>>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> Start uncovering the many advantages of virtual appliances >>>>> and start using them to simplify application deployment and >>>>> accelerate your shift to cloud computing. >>>>> http://p.sf.net/sfu/novell-sfdev2dev >>>>> >>>>> >>>>> ------------------------------------------------------------------------------ >>>>> >>>>> >>>>> _______________________________________________ >>>>> GDAlgorithms-list mailing list >>>>> GDA...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>>> Archives: >>>>> >>>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list------------------------------------------------------------------------------ >>>>> Start uncovering the many advantages of virtual appliances >>>>> and start using them to simplify application deployment and >>>>> accelerate your shift to cloud computing. >>>>> http://p.sf.net/sfu/novell-sfdev2dev_______________________________________________ >>>>> GDAlgorithms-list mailing list >>>>> GDA...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>>> Archives: >>>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> Start uncovering the many advantages of virtual appliances >>>> and start using them to simplify application deployment and >>>> accelerate your shift to cloud computing. >>>> http://p.sf.net/sfu/novell-sfdev2dev >>>> _______________________________________________ >>>> GDAlgorithms-list mailing list >>>> GDA...@li... >>>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>>> Archives: >>>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>> >>> ------------------------------------------------------------------------------ >>> Start uncovering the many advantages of virtual appliances >>> and start using them to simplify application deployment and >>> accelerate your shift to cloud computing. >>> http://p.sf.net/sfu/novell-sfdev2dev >>> _______________________________________________ >>> GDAlgorithms-list mailing list >>> GDA...@li... >>> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >>> Archives: >>> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >>> >> ------------------------------------------------------------------------------ >> Start uncovering the many advantages of virtual appliances >> and start using them to simplify application deployment and >> accelerate your shift to cloud computing. >> http://p.sf.net/sfu/novell-sfdev2dev >> _______________________________________________ >> GDAlgorithms-list mailing list >> GDA...@li... >> https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list >> Archives: >> http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list >> > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_name=gdalgorithms-list > |