WebKit Bugzilla
Attachment 348582 Details for
Bug 188940
: [WHLSL] Implement texture types
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
bug-188940-20180830192534.patch (text/plain), 86.65 KB, created by
Myles C. Maxfield
on 2018-08-30 19:25:35 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2018-08-30 19:25:35 PDT
Size:
86.65 KB
patch
obsolete
>Subversion Revision: 235529 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 5504221681915f596acbcbc36bea2b9b83db984d..99379603d075a66f710b179d2353c65df17eb9d2 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,36 @@ >+2018-08-30 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Implement texture types >+ https://bugs.webkit.org/show_bug.cgi?id=188940 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebGPUShadingLanguageRI/All.js: >+ * WebGPUShadingLanguageRI/Intrinsics.js: >+ (Intrinsics.): >+ (Intrinsics): >+ * WebGPUShadingLanguageRI/SPIRV.html: >+ * WebGPUShadingLanguageRI/StandardLibrary.js: >+ (let.standardLibrary): >+ * WebGPUShadingLanguageRI/Test.html: >+ * WebGPUShadingLanguageRI/Test.js: >+ (makeSampler): >+ (make1DTexture): >+ (make1DTextureArray): >+ (make2DTexture): >+ (make2DTextureArray): >+ (make3DTexture): >+ (makeTextureCube): >+ (makeRW1DTexture): >+ (makeRW1DTextureArray): >+ (makeRW2DTexture): >+ (makeRW2DTextureArray): >+ (makeRW3DTexture): >+ * WebGPUShadingLanguageRI/TextureOperations.js: Added. >+ (textureLoad): >+ (textureStore): >+ * WebGPUShadingLanguageRI/index.html: >+ > 2018-08-30 Wenson Hsieh <wenson_hsieh@apple.com> > > Followup to [iOS] TestWebKitAPI.PasteImage tests are flaky failures >diff --git a/Tools/WebGPUShadingLanguageRI/All.js b/Tools/WebGPUShadingLanguageRI/All.js >index 9c2a37150c1e976b926cfbee23437520a8de4a47..cc07fdb516616d328f38445e95a8205392e5da5a 100644 >--- a/Tools/WebGPUShadingLanguageRI/All.js >+++ b/Tools/WebGPUShadingLanguageRI/All.js >@@ -150,6 +150,7 @@ load("SynthesizeStructAccessors.js"); > load("SynthesizeCopyConstructorOperator.js"); > load("SynthesizeDefaultConstructorOperator.js"); > load("TernaryExpression.js"); >+load("TextureOperations.js"); > load("TrapStatement.js"); > load("TypeDef.js"); > load("TypeDefResolver.js"); >diff --git a/Tools/WebGPUShadingLanguageRI/Intrinsics.js b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >index b004067f5ebfb3a8b4bd98e437a8c0768be26f1e..ea394e42fbae452ccc94708a354c841f6c351ca2 100644 >--- a/Tools/WebGPUShadingLanguageRI/Intrinsics.js >+++ b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >@@ -330,7 +330,8 @@ class Intrinsics { > "native typedef sampler", > type => { > this.sampler = type; >- // FIXME: Figure out what to put here. >+ type.size = 1; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, {}); > }); > > for (let textureType of ["Texture1D", "RWTexture1D", "Texture1DArray", "RWTexture1DArray", "Texture2D", "RWTexture2D", "Texture2DArray", "RWTexture2DArray", "Texture3D", "RWTexture3D", "TextureCube"]) { >@@ -339,12 +340,16 @@ class Intrinsics { > `native typedef ${textureType}<${typeArgument}>`, > type => { > this[`${textureType}<${typeArgument}>`] = type; >+ type.size = 1; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, {}); > }); > for (let i = 2; i <= 4; ++i) { > this._map.set( > `native typedef ${textureType}<${typeArgument}${i}>`, > type => { > this[`${textureType}<${typeArgument}${i}>`] = type; >+ type.size = 1; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, {}); > }); > } > } >@@ -356,6 +361,8 @@ class Intrinsics { > `native typedef ${textureType}<${typeArgument}>`, > type => { > this[`${textureType}<${typeArgument}>`] = type; >+ type.size = 1; >+ type.populateDefaultValue = (buffer, offset) => buffer.set(offset, {}); > }); > } > } >@@ -914,6 +921,745 @@ class Intrinsics { > > for (let setter of BuiltinMatrixSetter.functions()) > this._map.set(setter.toString(), func => setter.instantiateImplementation(func)); >+ >+ for (let type of ["bool", "uchar", "ushort", "uint", "char", "short", "int", "half", "float"]) { >+ this._map.set( >+ `native ${type} Sample(Texture1D<${type}>,sampler,float location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Sample(Texture1D<${type}>,sampler,float location,int offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture1D<${type}>,int2 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1)])); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture1D<${type}>,int2 location,int offset)`, >+ func => { >+ func.implementation = function ([texture, location, offset]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1) + offset.loadValue()])); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(Texture1D<${type}>,uint MipLevel,uint* thread Width,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (mipID >= tex.length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ width.loadValue().copyFrom(EPtr.box(tex[mipID].length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native ${type} Sample(Texture1DArray<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Sample(Texture1DArray<${type}>,sampler,float2 location,int offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture1DArray<${type}>,int3 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2)])); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture1DArray<${type}>,int3 location,int offset)`, >+ func => { >+ func.implementation = function ([texture, location, offset]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2) + offset.loadValue()])); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(Texture1DArray<${type}>,uint MipLevel,uint* thread Width,uint* thread Elements,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, elements, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "No elements in the texture array"); >+ if (mipID >= tex[0].length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ width.loadValue().copyFrom(EPtr.box(tex[0][mipID].length), 1); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native ${type} Sample(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Sample(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleBias(Texture2D<${type}>,sampler,float2 location,float Bias)`, >+ func => { >+ func.implementation = function([texture, sampler, location, bias]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleBias(Texture2D<${type}>,sampler,float2 location,float Bias,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, bias, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleGrad(Texture2D<${type}>,sampler,float2 location,float2 DDX,float2 DDY)`, >+ func => { >+ func.implementation = function([texture, sampler, location, ddx, ddy]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleGrad(Texture2D<${type}>,sampler,float2 location,float2 DDX,float2 DDY,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, ddx, ddy, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleLevel(Texture2D<${type}>,sampler,float2 location,float LOD)`, >+ func => { >+ func.implementation = function([texture, sampler, location, lod]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleLevel(Texture2D<${type}>,sampler,float2 location,float LOD,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, lod, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture2D<${type}>,sampler,float2 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture2D<${type}>,sampler,float2 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture2D<${type}>,int3 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2)])); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture2D<${type}>,int3 location,int2 offset)`, >+ func => { >+ func.implementation = function ([texture, location, offset]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1) + offset.get(0), location.get(2) + offset.get(1)])); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(Texture2D<${type}>,uint MipLevel,uint* thread Width,uint* thread Height,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, height, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (mipID >= tex.length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ if (tex[mipID].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ height.loadValue().copyFrom(EPtr.box(tex[mipID].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[mipID][0].length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native ${type} Sample(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Sample(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleBias(Texture2DArray<${type}>,sampler,float3 location,float Bias)`, >+ func => { >+ func.implementation = function([texture, sampler, location, bias]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleBias(Texture2DArray<${type}>,sampler,float3 location,float Bias,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, bias, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleGrad(Texture2DArray<${type}>,sampler,float3 location,float2 DDX,float2 DDY)`, >+ func => { >+ func.implementation = function([texture, sampler, location, ddx, ddy]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleGrad(Texture2DArray<${type}>,sampler,float3 location,float2 DDX,float2 DDY,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, ddx, ddy, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleLevel(Texture2DArray<${type}>,sampler,float3 location,float LOD)`, >+ func => { >+ func.implementation = function([texture, sampler, location, lod]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleLevel(Texture2DArray<${type}>,sampler,float3 location,float LOD,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, lod, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture2DArray<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture2DArray<${type}>,sampler,float3 location,int2 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture2DArray<${type}>,int4 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2), location.get(3)])); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture2DArray<${type}>,int4 location,int2 offset)`, >+ func => { >+ func.implementation = function ([texture, location, offset]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2) + offset.get(0), location.get(3) + offset.get(1)])); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(Texture2DArray<${type}>,uint MipLevel,uint* thread Width,uint* thread Height,uint* thread Elements,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, height, elements, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "No elements in the texture array"); >+ if (mipID >= tex[0].length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ if (tex[0][mipID].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ height.loadValue().copyFrom(EPtr.box(tex[0][mipID].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][mipID][0].length), 1); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native ${type} Sample(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Sample(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture3D<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(Texture3D<${type}>,sampler,float3 location,int3 offset)`, >+ func => { >+ func.implementation = function([texture, sampler, location, offset]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture3D<${type}>,int4 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2), location.get(3)])); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(Texture3D<${type}>,int4 location,int3 offset)`, >+ func => { >+ func.implementation = function ([texture, location, offset]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1) + offset.get(0), location.get(2) + offset.get(1), location.get(3) + offset.get(2)])); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(Texture3D<${type}>,uint MipLevel,uint* thread Width,uint* thread Height,uint* thread Depth,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, height, depth, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (mipID >= tex.length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ if (tex[mipID].length == 0) >+ throw new WTrapError("[load]", "Texture has zero depth"); >+ if (tex[mipID][0].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ depth.loadValue().copyFrom(EPtr.box(tex[mipID].length), 1); >+ height.loadValue().copyFrom(EPtr.box(tex[mipID][0].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[mipID][0][0].length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native ${type} Sample(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleBias(TextureCube<${type}>,sampler,float3 location,float Bias)`, >+ func => { >+ func.implementation = function([texture, sampler, location, bias]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleGrad(TextureCube<${type}>,sampler,float3 location,float3 DDX,float3 DDY)`, >+ func => { >+ func.implementation = function([texture, sampler, location, ddx, ddy]) { >+ } >+ }); >+ this._map.set( >+ `native ${type} SampleLevel(TextureCube<${type}>,sampler,float3 location,float LOD)`, >+ func => { >+ func.implementation = function([texture, sampler, location, lod]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 Gather(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherRed(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherGreen(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherBlue(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native ${type}4 GatherAlpha(TextureCube<${type}>,sampler,float3 location)`, >+ func => { >+ func.implementation = function([texture, sampler, location]) { >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(TextureCube<${type}>,uint MipLevel,uint* thread Width,uint* thread Height,uint* thread NumberOfLevels)`, >+ func => { >+ func.implementation = function([texture, miplevel, width, height, numberOfLevels]) { >+ let tex = texture.loadValue(); >+ let mipID = miplevel.loadValue(); >+ if (tex.length != 6) >+ throw new WTrapError("[load]", "Cube texture doesn't have 6 faces"); >+ if (mipID >= tex[0].length) >+ throw new WTrapError("[load]", "Reading from nonexistant mip level of texture"); >+ if (tex[0][mipID].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ height.loadValue().copyFrom(EPtr.box(tex[0][mipID].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][mipID][0].length), 1); >+ numberOfLevels.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ >+ this._map.set( >+ `native void GetDimensions(RWTexture1D<${type}>,uint* thread Width)`, >+ func => { >+ func.implementation = function([texture, width]) { >+ width.loadValue().copyFrom(EPtr.box(texture.loadValue().length), 1); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(RWTexture1D<${type}>,float* thread Width)`, >+ func => { >+ func.implementation = function([texture, width]) { >+ width.loadValue().copyFrom(EPtr.box(texture.loadValue().length), 1); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(RWTexture1D<${type}>,int location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.loadValue()])); >+ } >+ }); >+ this._map.set( >+ `native void Store(RWTexture1D<${type}>,${type},uint location)`, >+ func => { >+ func.implementation = function ([texture, value, location]) { >+ textureStore(texture.loadValue(), value.loadValue(), [location.loadValue()]); >+ } >+ }); >+ >+ this._map.set( >+ `native void GetDimensions(RWTexture1DArray<${type}>,uint* thread Width,uint* thread Elements)`, >+ func => { >+ func.implementation = function([texture, width, elements]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no elements"); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(RWTexture1DArray<${type}>,float* thread Width,uint* thread Elements)`, >+ func => { >+ func.implementation = function([texture, width, elements]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no elements"); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(RWTexture1DArray<${type}>,int2 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1)])); >+ } >+ }); >+ this._map.set( >+ `native void Store(RWTexture1DArray<${type}>,${type},uint2 location)`, >+ func => { >+ func.implementation = function ([texture, value, location]) { >+ textureStore(texture.loadValue(), value.loadValue(), [location.get(0), location.get(1)]); >+ } >+ }); >+ >+ this._map.set( >+ `native void GetDimensions(RWTexture2D<${type}>,uint* thread Width,uint* thread Height)`, >+ func => { >+ func.implementation = function([texture, width, height]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ height.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(RWTexture2D<${type}>,float* thread Width,float* thread Height)`, >+ func => { >+ func.implementation = function([texture, width, height]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ height.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(RWTexture2D<${type}>,int2 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1)])); >+ } >+ }); >+ this._map.set( >+ `native void Store(RWTexture2D<${type}>,${type},uint2 location)`, >+ func => { >+ func.implementation = function ([texture, value, location]) { >+ textureStore(texture.loadValue(), value.loadValue(), [location.get(0), location.get(1)]); >+ } >+ }); >+ >+ this._map.set( >+ `native void GetDimensions(RWTexture2DArray<${type}>,uint* thread Width,uint* thread Height,uint* thread Elements)`, >+ func => { >+ func.implementation = function([texture, width, height, elements]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no elements"); >+ if (tex[0].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ height.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(RWTexture2DArray<${type}>,float* thread Width,float* thread Height,float* thread Elements)`, >+ func => { >+ func.implementation = function([texture, width, height, elements]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no elements"); >+ if (tex[0].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ elements.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ height.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(RWTexture2DArray<${type}>,int3 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2)])); >+ } >+ }); >+ this._map.set( >+ `native void Store(RWTexture2DArray<${type}>,${type},uint3 location)`, >+ func => { >+ func.implementation = function ([texture, value, location]) { >+ textureStore(texture.loadValue(), value.loadValue(), [location.get(0), location.get(1), location.get(2)]); >+ } >+ }); >+ >+ this._map.set( >+ `native void GetDimensions(RWTexture3D<${type}>,uint* thread Width,uint* thread Height,uint* thread Depth)`, >+ func => { >+ func.implementation = function([texture, width, height, depth]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no depth"); >+ if (tex[0].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ depth.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ height.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native void GetDimensions(RWTexture3D<${type}>,float* thread Width,float* thread Height,float* thread Depth)`, >+ func => { >+ func.implementation = function([texture, width, height, depth]) { >+ let tex = texture.loadValue(); >+ if (tex.length == 0) >+ throw new WTrapError("[load]", "Texture has no depth"); >+ if (tex[0].length == 0) >+ throw new WTrapError("[load]", "Texture has no rows"); >+ depth.loadValue().copyFrom(EPtr.box(tex.length), 1); >+ height.loadValue().copyFrom(EPtr.box(tex[0].length), 1); >+ width.loadValue().copyFrom(EPtr.box(tex[0][0].length), 1); >+ } >+ }); >+ this._map.set( >+ `native ${type} Load(RWTexture3D<${type}>,int3 location)`, >+ func => { >+ func.implementation = function ([texture, location]) { >+ return EPtr.box(textureLoad(texture.loadValue(), [location.get(0), location.get(1), location.get(2)])); >+ } >+ }); >+ this._map.set( >+ `native void Store(RWTexture3D<${type}>,${type},uint3 location)`, >+ func => { >+ func.implementation = function ([texture, value, location]) { >+ textureStore(texture.loadValue(), value.loadValue(), [location.get(0), location.get(1), location.get(2)]); >+ } >+ }); >+ >+ function boxVector(a) >+ { >+ let result = new EPtr(new EBuffer(a.length), 0); >+ for (let i = 0; i < a.length; ++i) >+ result.set(i, a[i]); >+ return result; >+ } >+ >+ for (let length of [2, 3, 4]) { >+ } >+ } > } > > add(thing) >diff --git a/Tools/WebGPUShadingLanguageRI/SPIRV.html b/Tools/WebGPUShadingLanguageRI/SPIRV.html >index 78d008f835f9e9c234ef2df6d6deea3f7426ce65..ddc65e367dd999ddb17d29cf6c5c6e62541d2a71 100644 >--- a/Tools/WebGPUShadingLanguageRI/SPIRV.html >+++ b/Tools/WebGPUShadingLanguageRI/SPIRV.html >@@ -133,6 +133,7 @@ td { > <script src="SynthesizeCopyConstructorOperator.js"></script> > <script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TernaryExpression.js"></script> >+ <script src="TextureOperations.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >index 3dd4fee18600d5cd2a895ad5a479721da7788cc1..21a8d292b8fbb58eac9803db80a4e3301aed5cda 100644 >--- a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >+++ b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >@@ -1897,9 +1897,10 @@ let standardLibrary = (function() { > print(`native void InterlockedCompareExchange(thread atomic_${type}*, ${type}, ${type}, thread ${type}*);`); > } > print(); >- >+ */ >+ > for (var type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) { >- for (var length of [``, `2`, `3`, `4`]) { >+ for (var length of [``/*, `2`, `3`, `4`*/]) { > print(`native ${type}${length} Sample(Texture1D<${type}${length}>, sampler, float location);`); > print(`native ${type}${length} Sample(Texture1D<${type}${length}>, sampler, float location, int offset);`); > print(`native ${type}${length} Load(Texture1D<${type}${length}>, int2 location);`); >@@ -2010,7 +2011,8 @@ let standardLibrary = (function() { > print(); > } > } >- >+ >+ /* > for (var type of [`half`, `float`]) { > print(`native ${type} Sample(TextureDepth2D<${type}>, sampler, float2 location);`); > print(`native ${type} Sample(TextureDepth2D<${type}>, sampler, float2 location, int2 offset);`); >diff --git a/Tools/WebGPUShadingLanguageRI/Test.html b/Tools/WebGPUShadingLanguageRI/Test.html >index 607a6953253da727b1de37678ec388b4fa240405..69c910492ed11ab2b30e2783eaf7ebbffdfe160a 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.html >+++ b/Tools/WebGPUShadingLanguageRI/Test.html >@@ -127,6 +127,7 @@ > <script src="SynthesizeCopyConstructorOperator.js"></script> > <script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TernaryExpression.js"></script> >+<script src="TextureOperations.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> >@@ -152,7 +153,7 @@ > <script> > function doTestInBrowser() > { >- var tester = doTest(/.*/); >+ var tester = doTest(/texture/); > var lastTime; > function next() > { >diff --git a/Tools/WebGPUShadingLanguageRI/Test.js b/Tools/WebGPUShadingLanguageRI/Test.js >index 000d05407115850ff30ec2366aeb185ac573dcd3..495fefe9d395ad6c08dd9f0bf874eb228fb02832 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.js >+++ b/Tools/WebGPUShadingLanguageRI/Test.js >@@ -94,6 +94,157 @@ function makeEnum(program, enumName, value) > return TypedValue.box(enumType, enumMember.value.unifyNode.valueForSelectedType); > } > >+function makeSampler(program, dict) >+{ >+ // enum WebGPUAddressMode { >+ // "clampToEdge", >+ // "repeat", >+ // "mirrorRepeat", >+ // "clampToBorderColor" >+ // } >+ // >+ // enum WebGPUFilterMode { >+ // "nearest", >+ // "linear" >+ // } >+ // >+ // enum WebGPUCompareFunction { >+ // "never", >+ // "less", >+ // "equal", >+ // "lessEqual", >+ // "greater", >+ // "notEqual", >+ // "greaterEqual", >+ // "always" >+ // } >+ // >+ // enum WebGPUBorderColor { >+ // "transparentBlack", >+ // "opaqueBlack", >+ // "opaqueWhite" >+ // } >+ // >+ // dictionary WebGPUSamplerDescriptor { >+ // WebGPUddressMode rAddressMode = "clampToEdge"; >+ // WebGPUddressMode sAddressMode = "clampToEdge"; >+ // WebGPUddressMode tAddressMode = "clampToEdge"; >+ // WebGPUFilterModeEnum magFilter = "nearest"; >+ // WebGPUFilterModeEnum minFilter = "nearest"; >+ // WebGPUFilterModeEnum mipmapFilter = "nearest"; >+ // float lodMinClamp = 0; >+ // float lodMaxClamp = Number.MAX_VALUE; >+ // unsigned long maxAnisotropy = 1; >+ // WebGPUCompareFunction compareFunction = "never"; >+ // WebGPUBorderColor borderColor = "transparentBlack"; >+ // }; >+ >+ let samplerData = {}; >+ samplerData.rAddressMode = dict.rAddressMode, >+ samplerData.sAddressMode = dict.sAddressMode, >+ samplerData.tAddressMode = dict.tAddressMode, >+ samplerData.magFilter = dict.magFilter; >+ samplerData.minFilter = dict.minFilter >+ samplerData.mipmapFilter = dict.mipmapFilter; >+ samplerData.lodMinClamp = dict.lodMinClamp, >+ samplerData.lodMaxClamp = dict.lodMaxClamp, >+ samplerData.maxAnisotropy = dict.maxAnisotropy, >+ samplerData.compareFunction = dict.compareFunction; >+ samplerData.borderColor = dict.borderColor; >+ >+ if (samplerData.rAddressMode == undefined) >+ samplerData.rAddressMode = "clampToEdge"; >+ if (samplerData.sAddressMode == undefined) >+ samplerData.sAddressMode = "clampToEdge"; >+ if (samplerData.tAddressMode == undefined) >+ samplerData.tAddressMode = "clampToEdge"; >+ if (samplerData.minFilter == undefined) >+ samplerData.minFilter = "nearest"; >+ if (samplerData.magFilter == undefined) >+ samplerData.magFilter = "nearest"; >+ if (samplerData.mipFilter == undefined) >+ samplerData.mipFilter = "nearest"; >+ if (samplerData.lodMinClamp == undefined) >+ samplerData.lodMinClamp = 0; >+ if (samplerData.lodMaxClamp == undefined) >+ samplerData.lodMaxClamp = Number.MAX_VALUE; >+ if (samplerData.maxAnisotropy == undefined) >+ samplerData.maxAnisotropy = 1; >+ if (samplerData.compareFunction == undefined) >+ samplerData.compareFunction = "never"; >+ if (samplerData.borderColor == undefined) >+ samplerData.borderColor = "transparentBlack"; >+ return TypedValue.box(program.intrinsics.sampler, samplerData); >+} >+ >+// Elements may either be a number or a vector of 2-4 numbers. >+// 1D Texture: An array of mipmaps. The first mipmap is the full size, and is a power-of-two. Each mipmap is half-size of the previous size. >+// 1D Texture Array: An array of 1D textures >+// 2D Texture: An array of mipmaps. The first mipmap is a rectangular array of rows, and each row is an array of elements. Both the row and column counts must be powers of two. Each mipmap is half-width and half-height of the previous size. >+// 2D Texture Array: An array of 2D textures >+// 3D Texture: An array of mipmaps. The first mipmap is a rectangular array of columns, each column is an array of rows, and each row is an array of elements. Both depth, row, and column counts must be powers of two. Each mipmap is half-depth, half-height, and half-width of the previous size. >+// Texture Cube: An array of 6 2D textures. >+// RW 1D Texture: An array of elements. The width must be a power-of-two. >+// RW 1D Texture Array: An array of RW 1D textures >+// RW 2D Texture: A rectangular array of rows, and each row is an array of elements. Both the row and column counts must be powers of two. >+// RW 2D Texture Array: An array of RW 2D textures >+// RW 3D Texture: A rectangular array of columns, each column is an array of rows, and each row is an array of elements. Both depth, row, and column counts must be powers of two. >+ >+function make1DTexture(program, mipmaps, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`Texture1D<${elementType}>`], mipmaps); >+} >+ >+function make1DTextureArray(program, array, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`Texture1DArray<${elementType}>`], array); >+} >+ >+function make2DTexture(program, mipmaps, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`Texture2D<${elementType}>`], mipmaps); >+} >+ >+function make2DTextureArray(program, array, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`Texture2DArray<${elementType}>`], array); >+} >+ >+function make3DTexture(program, mipmaps, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`Texture3D<${elementType}>`], mipmaps); >+} >+ >+function makeTextureCube(program, array, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`TextureCube<${elementType}>`], array); >+} >+ >+function makeRW1DTexture(program, elements, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`RWTexture1D<${elementType}>`], elements); >+} >+ >+function makeRW1DTextureArray(program, array, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`RWTexture1DArray<${elementType}>`], array); >+} >+ >+function makeRW2DTexture(program, rows, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`RWTexture2D<${elementType}>`], rows); >+} >+ >+function makeRW2DTextureArray(program, array, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`RWTexture2DArray<${elementType}>`], array); >+} >+ >+function makeRW3DTexture(program, depth, elementType) >+{ >+ return TypedValue.box(program.intrinsics[`RWTexture3D<${elementType}>`], depth); >+} >+ > function checkNumber(program, result, expected) > { > if (!result.type.unifyNode.isNumber) >@@ -5582,7 +5733,370 @@ tests.DISABLED_arrayIndex = function() { > checkInt(program, callFunction(program, "arrayIndexing", [ makeUint(program, 0), makeUint(program, 2) ]), 3); > checkInt(program, callFunction(program, "arrayIndexing", [ makeUint(program, 1), makeUint(program, 0) ]), 4); > checkInt(program, callFunction(program, "arrayIndexing", [ makeUint(program, 1), makeUint(program, 1) ]), 5); >- checkInt(program, callFunction(program, "arrayIndexing", [ makeUint(program, 1), makeUint(program, 2) ]), 6); >+ checkInt(program, callFunction(program, "arrayIndexing", [ makeUint(program, 1), makeUint(program, 2) ]), 6); >+} >+ >+tests.textureDimensions = function() { >+ let program = doPrep(` >+ uint foo1(Texture1D<float> texture) { >+ uint width; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &numberOfLevels); >+ return width; >+ } >+ uint foo2(Texture1D<float> texture) { >+ uint width; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo3(Texture1DArray<float> texture) { >+ uint width; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &elements, &numberOfLevels); >+ return width; >+ } >+ uint foo4(Texture1DArray<float> texture) { >+ uint width; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &elements, &numberOfLevels); >+ return elements; >+ } >+ uint foo5(Texture1DArray<float> texture) { >+ uint width; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &elements, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo6(Texture2D<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return width; >+ } >+ uint foo7(Texture2D<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return height; >+ } >+ uint foo8(Texture2D<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo9(Texture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &elements, &numberOfLevels); >+ return width; >+ } >+ uint foo10(Texture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &elements, &numberOfLevels); >+ return height; >+ } >+ uint foo11(Texture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &elements, &numberOfLevels); >+ return elements; >+ } >+ uint foo12(Texture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &elements, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo13(Texture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &depth, &numberOfLevels); >+ return width; >+ } >+ uint foo14(Texture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &depth, &numberOfLevels); >+ return height; >+ } >+ uint foo15(Texture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &depth, &numberOfLevels); >+ return depth; >+ } >+ uint foo16(Texture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &depth, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo17(TextureCube<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return width; >+ } >+ uint foo18(TextureCube<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return height; >+ } >+ uint foo19(TextureCube<float> texture) { >+ uint width; >+ uint height; >+ uint numberOfLevels; >+ GetDimensions(texture, 0, &width, &height, &numberOfLevels); >+ return numberOfLevels; >+ } >+ uint foo20(RWTexture1D<float> texture) { >+ uint width; >+ GetDimensions(texture, &width); >+ return width; >+ } >+ uint foo21(RWTexture1DArray<float> texture) { >+ uint width; >+ uint elements; >+ GetDimensions(texture, &width, &elements); >+ return width; >+ } >+ uint foo22(RWTexture1DArray<float> texture) { >+ uint width; >+ uint elements; >+ GetDimensions(texture, &width, &elements); >+ return elements; >+ } >+ uint foo23(RWTexture2D<float> texture) { >+ uint width; >+ uint height; >+ GetDimensions(texture, &width, &height); >+ return width; >+ } >+ uint foo24(RWTexture2D<float> texture) { >+ uint width; >+ uint height; >+ GetDimensions(texture, &width, &height); >+ return height; >+ } >+ uint foo25(RWTexture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ GetDimensions(texture, &width, &height, &elements); >+ return width; >+ } >+ uint foo26(RWTexture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ GetDimensions(texture, &width, &height, &elements); >+ return height; >+ } >+ uint foo27(RWTexture2DArray<float> texture) { >+ uint width; >+ uint height; >+ uint elements; >+ GetDimensions(texture, &width, &height, &elements); >+ return elements; >+ } >+ uint foo28(RWTexture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ GetDimensions(texture, &width, &height, &depth); >+ return width; >+ } >+ uint foo29(RWTexture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ GetDimensions(texture, &width, &height, &depth); >+ return height; >+ } >+ uint foo30(RWTexture3D<float> texture) { >+ uint width; >+ uint height; >+ uint depth; >+ GetDimensions(texture, &width, &height, &depth); >+ return depth; >+ } >+ `); >+ let texture1D = make1DTexture(program, [[1, 7, 14, 79], [13, 16], [15]], "float"); >+ let texture1DArray = make1DTextureArray(program, [[[1, 7, 14, 79], [13, 16], [15]], [[16, 17, 18, 19], [20, 21], [22]]], "float"); >+ let texture2D = make2DTexture(program, [ >+ [[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]] >+ ], "float"); >+ let texture2DArray = make2DTextureArray(program, [[ >+ [[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]] >+ ]], "float"); >+ let texture3D = make3DTexture(program, [ >+ [[[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]], >+ [[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]]] >+ ], "float"); >+ let textureCube = makeTextureCube(program, [[ >+ [[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]], >+ ]], "float"); >+ let rwTexture1D = makeRW1DTexture(program, [1, 2, 3, 4, 5, 6, 7, 8], "float"); >+ let rwTexture1DArray = makeRW1DTextureArray(program, [[1, 2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23, 24]], "float"); >+ let rwTexture2D = makeRW2DTexture(program, [ >+ [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]], "float"); >+ let rwTexture2DArray = makeRW2DTextureArray(program, [ >+ [[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]]], "float"); >+ let rwTexture3D = makeRW3DTexture(program, [ >+ [[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]]], "float"); >+ checkUint(program, callFunction(program, "foo1", [texture1D]), 4); >+ checkUint(program, callFunction(program, "foo2", [texture1D]), 3); >+ checkUint(program, callFunction(program, "foo3", [texture1DArray]), 4); >+ checkUint(program, callFunction(program, "foo4", [texture1DArray]), 2); >+ checkUint(program, callFunction(program, "foo5", [texture1DArray]), 3); >+ checkUint(program, callFunction(program, "foo6", [texture2D]), 8); >+ checkUint(program, callFunction(program, "foo7", [texture2D]), 4); >+ checkUint(program, callFunction(program, "foo8", [texture2D]), 3); >+ checkUint(program, callFunction(program, "foo9", [texture2DArray]), 8); >+ checkUint(program, callFunction(program, "foo10", [texture2DArray]), 4); >+ checkUint(program, callFunction(program, "foo11", [texture2DArray]), 2); >+ checkUint(program, callFunction(program, "foo12", [texture2DArray]), 3); >+ checkUint(program, callFunction(program, "foo13", [texture3D]), 8); >+ checkUint(program, callFunction(program, "foo14", [texture3D]), 4); >+ checkUint(program, callFunction(program, "foo15", [texture3D]), 2); >+ checkUint(program, callFunction(program, "foo16", [texture3D]), 2); >+ checkUint(program, callFunction(program, "foo17", [textureCube]), 2); >+ checkUint(program, callFunction(program, "foo18", [textureCube]), 4); >+ checkUint(program, callFunction(program, "foo19", [textureCube]), 2); >+ checkUint(program, callFunction(program, "foo20", [rwTexture1D]), 8); >+ checkUint(program, callFunction(program, "foo21", [rwTexture1DArray]), 8); >+ checkUint(program, callFunction(program, "foo22", [rwTexture1DArray]), 3); >+ checkUint(program, callFunction(program, "foo23", [rwTexture2D]), 8); >+ checkUint(program, callFunction(program, "foo24", [rwTexture2D]), 4); >+ checkUint(program, callFunction(program, "foo25", [rwTexture2DArray]), 8); >+ checkUint(program, callFunction(program, "foo26", [rwTexture2DArray]), 4); >+ checkUint(program, callFunction(program, "foo27", [rwTexture2DArray]), 2); >+ checkUint(program, callFunction(program, "foo28", [rwTexture3D]), 8); >+ checkUint(program, callFunction(program, "foo29", [rwTexture3D]), 4); >+ checkUint(program, callFunction(program, "foo30", [rwTexture3D]), 2); >+} >+ >+tests.textureLoad = function() { >+ let program = doPrep(` >+ float foo(Texture1D<float> texture, int mipmap, int location) { >+ return Load(texture, int2(mipmap, location)); >+ } >+ `); >+ checkFloat(program, callFunction(program, "foo", [make1DTexture(program, [[1, 7, 14, 79], [13, 16], [15]], "float"), makeInt(program, 0), makeInt(program, 1)]), 7); >+ checkFloat(program, callFunction(program, "foo", [make1DTexture(program, [[1, 7, 14, 79], [13, 16], [15]], "float"), makeInt(program, 1), makeInt(program, 1)]), 16); > } > > okToTest = true; >diff --git a/Tools/WebGPUShadingLanguageRI/TextureOperations.js b/Tools/WebGPUShadingLanguageRI/TextureOperations.js >new file mode 100644 >index 0000000000000000000000000000000000000000..f4b8993a9de15c2a267a1336875a2099d14e3a85 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/TextureOperations.js >@@ -0,0 +1,484 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+"use strict"; >+ >+function textureLoad(texture, path) >+{ >+ for (var index of path) { >+ if (index < 0 || index >= texture.length) >+ throw new WTrapError("[Load]", "Texture read out of bounds"); >+ texture = texture[index]; >+ } >+ return texture; >+} >+ >+function textureStore(texture, value, path) >+{ >+ do { >+ if (path.length == 0) >+ throw new Error("Zero-length store path"); >+ if (path.length == 1) { >+ texture[path[0]] = value; >+ return; >+ } else { >+ texture = texture[path[0]]; >+ path.shift(); >+ } >+ } while (true); >+} >+ >+function depthCompareOperation(dref, d, compareFunction) >+{ >+ // Vulkan 1.1.83 section 15.3.4 >+ switch (compareFunction) { >+ case "never": >+ return 0; >+ case "less": >+ return dref < d ? 1 : 0; >+ case "equal": >+ return dref == d ? 1 : 0; >+ case "lessEqual": >+ return dref <= d ? 1 : 0; >+ case "greater": >+ return dref > d ? 1 : 0; >+ case "notEqual": >+ return dref != d ? 1 : 0; >+ case "greaterEqual": >+ return dref >= d ? 1 : 0; >+ case "always": >+ return 1; >+ default: >+ throw new Error("Unknown depth comparison function"); >+ } >+} >+ >+function conversionToRGBA(value) >+{ >+ // Vulkan 1.1.83 section 15.3.5 >+ if (value instanceof Array) { >+ var result = []; >+ for (let i = 0; i < value.length; ++i) >+ result.push(value[i]); >+ while (result.length != 4) >+ result.push(result.length == 3 ? 1 : 0); >+ return result; >+ } else >+ return [value, 0, 0, 1]; >+} >+ >+//For explicit LOD image instructions, if the optional SPIR-V operand Grad is provided, then the operand values are used for the derivatives. The number of components present in each derivative for a given image dimensionality matches the number of partial derivatives computed above. >+//If the optional SPIR-V operand Lod is provided, then derivatives are set to zero, the cube map derivative transformation is skipped, and the scale factor operation is skipped. Instead, the floating point scalar coordinate is directly assigned to λbase as described in Level-of-Detail Operation. >+function implicitDerivative() >+{ >+ // Vulkan 1.1.83 section 15.5 >+ return 0; >+} >+ >+function projectionOperation(s, t, r, dref, q) >+{ >+ // Vulkan 1.1.83 section 15.6.1 >+ return [s / q, t / q, r / q, dref / q]; >+} >+ >+function cubeMapFaceSelection(s, t, r, partialRxWithRespectToX, partialRxWithRespectToY, partialRyWithRespectToX, partialRyWithRespectToY, partialRzWithRespectToX, partialRzWithRespectToY) >+{ >+ // Vulkan 1.1.83 section 15.6.4 >+ let rx = s; >+ let ry = t; >+ let rz = r; >+ let winner = 0; >+ if (Math.abs(rz) >= Math.abs(ry) && Math.abs(rz) >= Math.abs(rx)) >+ winner = 2; >+ else if (Math.abs(ry) >= Math.abs(rx) && Math.abs(ry) >= Math.abs(rz)) >+ winner = 1; >+ >+ let layerNumber; >+ let sc; >+ let tc; >+ let rc; >+ let partialScWithRespectToX; >+ let partialScWithRespectToY; >+ let partialTcWithRespectToX; >+ let partialTcWithRespectToY; >+ let partialRcWithRespectToX; >+ let partialRcWithRespectToY; >+ if (winner == 0 && rx >= 0) { >+ layerNumber = 0; >+ sc = -rz; >+ tc = -ry; >+ rc = rx; >+ partialScWithRespectToX = -partialRzWithRespectToX; >+ partialScWithRespectToY = -partialRzWithRespectToY; >+ partialTcWithRespectToX = -partialRyWithRespectToX; >+ partialTcWithRespectToY = -partialRyWithRespectToY; >+ partialRcWithRespectToX = partialRxWithRespectToX; >+ partialRcWithRespectToY = partialRxWithRespectToY; >+ } else if (winner == 0) { >+ layerNumber = 1; >+ sc = rz; >+ tc = -ry; >+ rc = rx; >+ partialScWithRespectToX = partialRzWithRespectToX; >+ partialScWithRespectToY = partialRzWithRespectToY; >+ partialTcWithRespectToX = -partialRyWithRespectToX; >+ partialTcWithRespectToY = -partialRyWithRespectToY; >+ partialRcWithRespectToX = -partialRxWithRespectToX; >+ partialRcWithRespectToY = -partialRxWithRespectToY; >+ } else if (winner == 1 && ry >= 0) { >+ layerNumber = 2; >+ sc = rx; >+ tc = -rz; >+ rc = ry; >+ partialScWithRespectToX = partialRxWithRespectToX; >+ partialScWithRespectToY = partialRxWithRespectToY; >+ partialTcWithRespectToX = partialRzWithRespectToX; >+ partialTcWithRespectToY = partialRzWithRespectToY; >+ partialRcWithRespectToX = partialRyWithRespectToX; >+ partialRcWithRespectToY = partialRyWithRespectToY; >+ } else if (winner == 1) { >+ layerNumber = 3; >+ sc = rx; >+ tc = -rz; >+ rc = ry; >+ partialScWithRespectToX = partialRxWithRespectToX; >+ partialScWithRespectToY = partialRxWithRespectToY; >+ partialTcWithRespectToX = -partialRzWithRespectToX; >+ partialTcWithRespectToY = -partialRzWithRespectToY; >+ partialRcWithRespectToX = -partialRyWithRespectToX; >+ partialRcWithRespectToY = -partialRyWithRespectToY; >+ } else if (winner == 2 && rz >= 0) { >+ layerNumber = 4; >+ sc = rx; >+ tc = -ry; >+ rc = rz; >+ partialScWithRespectToX = partialRxWithRespectToX; >+ partialScWithRespectToY = partialRxWithRespectToY; >+ partialTcWithRespectToX = -partialRyWithRespectToX; >+ partialTcWithRespectToY = -partialRyWithRespectToY; >+ partialRcWithRespectToX = partialRzWithRespectToX; >+ partialRcWithRespectToY = partialRzWithRespectToY; >+ } else { >+ layerNumber = 5; >+ sc = -rx; >+ tc = -ry; >+ rc = rz; >+ partialScWithRespectToX = -partialRxWithRespectToX; >+ partialScWithRespectToY = -partialRxWithRespectToY; >+ partialTcWithRespectToX = -partialRyWithRespectToX; >+ partialTcWithRespectToY = -partialRyWithRespectToY; >+ partialRcWithRespectToX = -partialRzWithRespectToX; >+ partialRcWithRespectToY = -partialRzWithRespectToY; >+ } >+ return [layerNumber, sc, tc, rc, partialScWithRespectToX, partialScWithRespectToY, partialTcWithRespectToX, partialTcWithRespectToY, partialRcWithRespectToX, partialRcWithRespectToY] >+} >+ >+function cubeMapCoordinateTransformation(sc, rc) >+{ >+ // Vulkan 1.1.83 section 15.6.5 >+ let sFace = (1 / 2) * sc / Math.abs(rc) + (1 / 2); >+ let tFace = (1 / 2) * tc / Math.abs(rc) + (1 / 2); >+ return [sFace, tFace]; >+} >+ >+function cubeMapDerivativeTransformation(sc, tc, rc, partialScWithRespectToX, partialScWithRespectToY, partialTcWithRespectToX, partialTcWithRespectToY, partialRcWithRespectToX, partialRcWithRespectToY) >+{ >+ // Vulkan 1.1.83 section 15.6.6 >+ let partialSFaceWithRespectToX = (1 / 2) * ((Math.abs(rc) * partialScWithRespectToX - sc * partialRcWithRespectToX) / Math.pow(rc, 2)); >+ let partialSFaceWithRespectToY = (1 / 2) * ((Math.abs(rc) * partialScWithRespectToY - sc * partialRcWithRespectToY) / Math.pow(rc, 2)); >+ let partialTFaceWithRespectToX = (1 / 2) * ((Math.abs(rc) * partialTcWithRespectToX - tc * partialRcWithRespectToX) / Math.pow(rc, 2)); >+ let partialTFaceWithRespectToY = (1 / 2) * ((Math.abs(rc) * partialTcWithRespectToY - tc * partialRcWithRespectToY) / Math.pow(rc, 2)); >+ return [partialSFaceWithRespectToX, partialSFaceWithRespectToY, partialTFaceWithRespectToX, partialTFaceWithRespectToY]; >+} >+ >+function scaleFactorOperation() >+{ >+ // Vulkan 1.1.83 section 15.6.7 >+ // FIXME: Implement this. >+} >+ >+function levelOfDetailOperation(maxSamplerLodBias, lodFromFunctionOperand, lodMinFromFunctionOperand, biasFromFunctionOperand, samplerBias, samplerLodMin, samplerLoadMax, rhoMax, eta) >+{ >+ // Vulkan 1.1.83 section 15.6.7 >+ let lambdaBase = lodFromFunctionOperand != undefined ? lodFromFunctionOperand : Math.log2(rhoMax / eta); >+ let lambdaPrime = lambdaBase + Math.min(Math.max(samplerBias + biasFromFunctionOperand, -maxSamplerLodBias), maxSamplerLodBias); >+ let lodMin = Math.max(samplerLodMin, lodMinFromFunctionOperand); >+ let lodMax = samplerLoadMax; >+ let lambda; >+ if (lambdaPrime > lodMax) >+ lambda = lodMax; >+ else if (lodMin <= lambdaPrime && lambdaPrime <= lodMax) >+ lambda = lambdaPrime; >+ else if (lambdaPrime < lodMin) >+ lambda = lodMin; >+ else >+ throw new Error("lodMin >= lodMax"); >+ return lambda; >+} >+ >+function imageLevelSelection(baseMipLevel, levelCount, mipmapMode, lambda) >+{ >+ // Vulkan 1.1.83 section 15.6.7 >+ function nearest(dPrime) >+ { >+ return Math.ceil(dPrime + 0.5) - 1; >+ } >+ >+ let q = levelCount - 1; >+ let dPrime = baseMipLevel + Math.min(Math.max(lambda, 0), q); >+ let dl; >+ if (mipmapMode == "nearest") >+ dl = nearest(dPrime); >+ else >+ dl = dPrime; >+ if (mipmapMode == "nearest") >+ return dl; >+ else { >+ let dHi = Math.floor(dl); >+ let dLow = Math.min(dHi + 1, q); >+ let delta = dl - dHi; >+ return [dHi, dLow, delta]; >+ } >+} >+ >+function strqaToUVWATransformation(s, t, r, width, height, depth) >+{ >+ // Vulkan 1.1.83 section 15.6.8 >+ let u = s * width; >+ let v = t * height; >+ let w = r * depth; >+ return [u, v, w]; >+} >+ >+function uvwaToIJKLNTransformationAndArrayLayerSelection(layerCount, baseArrayLayer, filter, u, v, w, a, deltaI, deltaJ, deltaK) >+{ >+ // Vulkan 1.1.83 section 15.7.1 >+ function rne(a) >+ { >+ return Math.floor(a + 0.5); >+ } >+ let l = Math.min(Math.max(rne(a), 0), layerCount - 1) + baseArrayLayer; >+ let i; >+ let j; >+ let k; >+ if (filter == "nearest") { >+ i = Math.floor(u); >+ j = Math.floor(v); >+ k = Math.floor(w); >+ >+ i += deltaI; >+ j += deltaJ; >+ k += deltaK; >+ >+ return [i, j, k, l]; >+ } else { >+ if (filter != "linear") >+ throw new Error("Unknown filter"); >+ let i0 = Math.floor(u - 0.5); >+ let i1 = i0 + 1; >+ let j0 = Math.floor(v - 0.5); >+ let j1 = j0 + 1; >+ let k0 = Math.floor(w - 0.5); >+ let k1 = k0 + 1; >+ let alpha = (u - 0.5) - i0; >+ let beta = (v - 0.5) - j0; >+ let gamma = (w - 0.5) - k0; >+ >+ i0 += deltaI; >+ i1 += deltaI; >+ j0 += deltaJ; >+ j1 += deltaJ; >+ k0 += deltaK; >+ k1 += deltaK; >+ >+ return [i0, i1, j0, j1, k0, k1, l, alpha, beta, gamma]; >+ } >+} >+ >+function integerTexelCoordinateOperations(baseMipLevel, levelCount, levelBase, lodFromFunctionOperand) >+{ >+ // Vulkan 1.1.83 section 15.8 >+ let d = levelBase + lodFromFunctionOperand; >+ if (d < baseMipLevel || d >= baseMipLevel + levelCount) >+ throw new Error("Selected level does not lie inside the image"); >+ return d; >+} >+ >+function wrappingOperation(width, height, depth, addressModeU, addressModeV, addressModeW, i, j, k) >+{ >+ // Vulkan 1.1.83 section 15.9.1 >+ // FIXME: Implement cube map handling >+ function transform(addressMode, size, i) >+ { >+ function mirror(n) { >+ if (n >= 0) >+ return n; >+ else >+ return -(1 + n); >+ } >+ switch (addressMode) { >+ case "clampToEdge": >+ return Math.min(Math.max(i, 0), size - 1); >+ case "repeat": >+ return i % size; >+ case "mirrorRepeat": >+ return (size - 1) - mirror((i % (2 * size)) - size); >+ case "clampToBorderColor": >+ return Math.min(Math.max(i, -1), size); >+ default >+ throw new Error("Unknown address mode"); >+ } >+ } >+ return [transform(addressModeU, width, i), transform(addressModeV, height, j), transform(addressModeW, depth, k)]; >+} >+ >+function texelGathering() >+{ >+ // Vulkan 1.1.83 section 15.9.2 >+ // FIXME: Implement this >+ /*let tauR = ; >+ let tauG = ; >+ let tauB = ; >+ let tauA = ;*/ >+} >+ >+function texelFiltering(baseMipLevel, levelCount, layerCount, baseArrayLayer, magFilter, minFilter, mipmapMode, addressModeU, addressModeV, addressModeW, borderColor, lambda, s, t, r, a, deltaI, deltaJ, deltaK, dimension, computeWidthCallback, computeHeightCallback, computeDepthCallback, accessElementCallback, accessRowCallback, accessDepthSliceCallback, accessLevelCallback, accessLayerCallback, borderCallback, data) >+{ >+ // Vulkan 1.1.83 section 15.9.3 >+ let filter; >+ if (lambda <= 0) >+ filter = magFilter; >+ else >+ filter = minFilter; >+ >+ function computeTau(level) >+ { >+ function reduce(...arguments) >+ { >+ if (arguments.length % 2 != 0) >+ throw new Error("Don't have a weight corresponding to each value"); >+ let sum = 0; >+ // FIXME: These arguments need to be averaged component-wise. >+ for (let i = 0; i < arguments.length / 2; ++i) >+ sum += arguments[2 * i] * arguments[2 * i + 1]; >+ return sum; >+ } >+ >+ function accessColor(width, height, depth, l, i, j, k) >+ { >+ function shouldBeBorder(value, max) >+ { >+ if (value < -1 || value > max) >+ throw new Error("Out-of-bounds texture read"); >+ return value == -1 || value == max); >+ } >+ >+ let [wrappedI, wrappedJ, wrappedK] = wrappingOperation(width, height, depth, addressModeU, addressModeV, addressModeW, i, j, k) >+ if (shouldBeBorder(i, width) || shouldBeBorder(j, height) || shouldBeBorder(k, depth)) >+ return borderCallback(borderColor); >+ else { >+ let layerData = accessLayerCallback(data, l); >+ let levelData = accessLevelCallback(layerData, level); >+ let depthSliceData = accessDepthSliceCallback(levelData, k); >+ let rowData = accessRowCallback(depthSliceData, j); >+ let element = accessElementCallback(rowData, i); >+ return element; >+ } >+ } >+ >+ // This is kind of bogus, because the width/height/depth depends on both the mipmap level and the array layer, but the spec calculates them at the same time. >+ // Luckily, there is no circular dependency, so we can calculate the "l" parameter, ignore the rest, and feed it back through again. >+ // This spec has some problems... >+ if (filter == "nearest") { >+ let [i, j, k, l] = uvwaToIJKLNTransformationAndArrayLayerSelection(layerCount, baseArrayLayer, filter, 0, 0, 0, level, deltaI, deltaJ, deltaK); >+ width = computeWidthCallback(level, l); >+ height = computeHeightCallback(level, l); >+ depth = computeDepthCallback(level, l); >+ let [u, v, w] = strqaToUVWATransformation(s, t, r, width, height, depth); >+ [i, j, k, l] = uvwaToIJKLNTransformationAndArrayLayerSelection(layerCount, baseArrayLayer, filter, u, v, w, level, deltaI, deltaJ, deltaK); >+ return accessColor(width, height, depth, l, i, j, k); >+ } else { >+ if (mipmapMode != "linear") >+ throw new Error("Unknown filter"); >+ let [i0, i1, j0, j1, k0, k1, l, alpha, beta, gamma] = uvwaToIJKLNTransformationAndArrayLayerSelection(layerCount, baseArrayLayer, filter, u, v, w, a, deltaI, deltaJ, deltaK); >+ width = computeWidthCallback(level, l); >+ height = computeHeightCallback(level, l); >+ depth = computeDepthCallback(level, l); >+ [u, v, w] = strqaToUVWATransformation(s, t, r, width, height, depth); >+ [i0, i1, j0, j1, k0, k1, l, alpha, beta, gamma] = uvwaToIJKLNTransformationAndArrayLayerSelection(layerCount, baseArrayLayer, filter, u, v, w, level, deltaI, deltaJ, deltaK); >+ let color000 = accessColor(width, height, depth, l, i0, j0, k0); >+ let color100 = accessColor(width, height, depth, l, i1, j0, k0); >+ let color010 = accessColor(width, height, depth, l, i0, j1, k0); >+ let color110 = accessColor(width, height, depth, l, i1, j1, k0); >+ let color001 = accessColor(width, height, depth, l, i0, j0, k1); >+ let color101 = accessColor(width, height, depth, l, i1, j0, k1); >+ let color011 = accessColor(width, height, depth, l, i0, j1, k1); >+ let color111 = accessColor(width, height, depth, l, i1, j1, k1); >+ switch (dimension) { >+ case 1: >+ let color0 = color011; >+ let color1 = color111; >+ return reduce(1 - alpha, color0, alpha, color1); >+ case 2: >+ let color00 = color001; >+ let color10 = color101; >+ let color01 = color011; >+ let color11 = color111; >+ return reduce((1 - alpha) * (1 - beta), color00, alpha * (1 - beta), color10, (1 - alpha) * beta, color01, alpha * beta, color11); >+ case 3: >+ return reduce( >+ (1 - alpha) * (1 - beta) * (1 - gamma), color000, >+ alpha * (1 - beta) * (1 - gamma), color100, >+ (1 - alpha) * beta * (1 - gamma), color010, >+ alpha * beta * (1 - gamma), color110, >+ (1 - alpha) * (1 - beta) * gamma, color001, >+ alpha * (1 - beta) * gamma, color101, >+ (1 - alpha) * beta * gamma, color011, >+ alpha * beta * gamma, color111); >+ default: >+ throw new Error("Unknown dimension"); >+ } >+ } >+ } >+ >+ if (mipmapMode == "nearest") { >+ let imageLevel = imageLevelSelection(baseMipLevel, levelCount, mipmapMode, lambda); >+ return computeTau(imageLevel); >+ } else { >+ if (mipmapMode != "linear") >+ throw new Error("Unknown filter"); >+ let [dHi, dLow, delta] = imageLevelSelection(baseMipLevel, levelCount, mipmapMode, lambda); >+ return reduce(1 - delta, computeTau(dHi), delta, computeTau(dLo)); >+ } >+} >+ >+function sample1D(texture, sampler, location) >+{ >+ let [s, t, r, dref] = projectionOperation(s, t, r, dref, q); >+ texelFiltering(); >+ depthCompareOperation() >+ // FIXME: Figure out what to do with anisotropy >+ // FIXME: WHLSL ddx ddy arguments >+ // FIXME: Figure out how to do multisampling. >+} >diff --git a/Tools/WebGPUShadingLanguageRI/index.html b/Tools/WebGPUShadingLanguageRI/index.html >index 65a86411b3e770b557b41acc7e414def42403013..8366bb18d170e93f800df5822fa5eafeb43bed83 100644 >--- a/Tools/WebGPUShadingLanguageRI/index.html >+++ b/Tools/WebGPUShadingLanguageRI/index.html >@@ -127,6 +127,7 @@ > <script src="SynthesizeCopyConstructorOperator.js"></script> > <script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TernaryExpression.js"></script> >+<script src="TextureOperations.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188940
:
348066
|
348347
|
348365
|
348376
|
348433
|
348459
|
348464
|
348467
|
348521
|
348581
|
348582
|
348607
|
348661
|
348687
|
348695
|
348698
|
348705
|
348717
|
348718
|
348723
|
348724
|
348726
|
348727
|
348752
|
348758
|
348775
|
348791
|
348797
|
348798
|
348800
|
348801
|
348804