How to pass a variable number of MTLTextures to a fragment shader?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
What is the correct syntax for passing a variable number of MTLTexture's as an array to a fragment shader?
This StackOverflow Question: "How to use texture2d_array array in metal?" mentions the use of:
array<texture2d<half>, 5>
However, this requires specifying the size of the array. In Metal Shading Language Specification.pdf (Sec. 2.11) they also demonstrate this type. However, they also refer to array_ref
but it's not clear to me how to use it, or if it's even allowed as a parameter type for a fragment shared given this statement:
"The array_ref type cannot be passed as an argument to graphics
and kernel functions."
What I'm currently doing is just declaring the parameter as:
fragment float4 fragmentShader(RasterizerData in [[ stage_in ]],
sampler s [[ sampler(0) ]],
const array<texture2d<half>, 128> textures [[ texture(0) ]]) {
const half4 c = textures[in.textureIndex].sample(s, in.coords);
}
Since the limit is 128 fragment textures. In any render pass, I might use between 1..n textures, where I ensure that n does not exceed 128. That seems to work for me, but am I Doing It Wrong?
My use-case is drawing a 2D plane that is sub-divided into a bunch of tiles. Each tile's content is sampled from a designated texture in the array based on a pre-computed texture index. The textures are set using setFragmentTexture:atIndex
in the correct order at the start of the render pass. The texture index is passed from the vertex shader to the fragment shader.
macos metal fragment-shader
add a comment |
What is the correct syntax for passing a variable number of MTLTexture's as an array to a fragment shader?
This StackOverflow Question: "How to use texture2d_array array in metal?" mentions the use of:
array<texture2d<half>, 5>
However, this requires specifying the size of the array. In Metal Shading Language Specification.pdf (Sec. 2.11) they also demonstrate this type. However, they also refer to array_ref
but it's not clear to me how to use it, or if it's even allowed as a parameter type for a fragment shared given this statement:
"The array_ref type cannot be passed as an argument to graphics
and kernel functions."
What I'm currently doing is just declaring the parameter as:
fragment float4 fragmentShader(RasterizerData in [[ stage_in ]],
sampler s [[ sampler(0) ]],
const array<texture2d<half>, 128> textures [[ texture(0) ]]) {
const half4 c = textures[in.textureIndex].sample(s, in.coords);
}
Since the limit is 128 fragment textures. In any render pass, I might use between 1..n textures, where I ensure that n does not exceed 128. That seems to work for me, but am I Doing It Wrong?
My use-case is drawing a 2D plane that is sub-divided into a bunch of tiles. Each tile's content is sampled from a designated texture in the array based on a pre-computed texture index. The textures are set using setFragmentTexture:atIndex
in the correct order at the start of the render pass. The texture index is passed from the vertex shader to the fragment shader.
macos metal fragment-shader
add a comment |
What is the correct syntax for passing a variable number of MTLTexture's as an array to a fragment shader?
This StackOverflow Question: "How to use texture2d_array array in metal?" mentions the use of:
array<texture2d<half>, 5>
However, this requires specifying the size of the array. In Metal Shading Language Specification.pdf (Sec. 2.11) they also demonstrate this type. However, they also refer to array_ref
but it's not clear to me how to use it, or if it's even allowed as a parameter type for a fragment shared given this statement:
"The array_ref type cannot be passed as an argument to graphics
and kernel functions."
What I'm currently doing is just declaring the parameter as:
fragment float4 fragmentShader(RasterizerData in [[ stage_in ]],
sampler s [[ sampler(0) ]],
const array<texture2d<half>, 128> textures [[ texture(0) ]]) {
const half4 c = textures[in.textureIndex].sample(s, in.coords);
}
Since the limit is 128 fragment textures. In any render pass, I might use between 1..n textures, where I ensure that n does not exceed 128. That seems to work for me, but am I Doing It Wrong?
My use-case is drawing a 2D plane that is sub-divided into a bunch of tiles. Each tile's content is sampled from a designated texture in the array based on a pre-computed texture index. The textures are set using setFragmentTexture:atIndex
in the correct order at the start of the render pass. The texture index is passed from the vertex shader to the fragment shader.
macos metal fragment-shader
What is the correct syntax for passing a variable number of MTLTexture's as an array to a fragment shader?
This StackOverflow Question: "How to use texture2d_array array in metal?" mentions the use of:
array<texture2d<half>, 5>
However, this requires specifying the size of the array. In Metal Shading Language Specification.pdf (Sec. 2.11) they also demonstrate this type. However, they also refer to array_ref
but it's not clear to me how to use it, or if it's even allowed as a parameter type for a fragment shared given this statement:
"The array_ref type cannot be passed as an argument to graphics
and kernel functions."
What I'm currently doing is just declaring the parameter as:
fragment float4 fragmentShader(RasterizerData in [[ stage_in ]],
sampler s [[ sampler(0) ]],
const array<texture2d<half>, 128> textures [[ texture(0) ]]) {
const half4 c = textures[in.textureIndex].sample(s, in.coords);
}
Since the limit is 128 fragment textures. In any render pass, I might use between 1..n textures, where I ensure that n does not exceed 128. That seems to work for me, but am I Doing It Wrong?
My use-case is drawing a 2D plane that is sub-divided into a bunch of tiles. Each tile's content is sampled from a designated texture in the array based on a pre-computed texture index. The textures are set using setFragmentTexture:atIndex
in the correct order at the start of the render pass. The texture index is passed from the vertex shader to the fragment shader.
macos metal fragment-shader
macos metal fragment-shader
asked Nov 16 '18 at 19:28
kennyckennyc
1,66231627
1,66231627
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You should consider an array texture instead of a texture array. That is, a texture whose type is MTLTextureType2DArray
. You use the arrayLength
property of the texture descriptor to specify how many 2-D slices the array texture contains.
To populate the texture, you specify which slice you're writing to with methods such as -replaceRegion:...
or -copyFrom{Buffer,Texture}:...toTexture:...
.
In a shader, you can specify which element to sample or read from using the array
parameter.
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344214%2fhow-to-pass-a-variable-number-of-mtltextures-to-a-fragment-shader%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You should consider an array texture instead of a texture array. That is, a texture whose type is MTLTextureType2DArray
. You use the arrayLength
property of the texture descriptor to specify how many 2-D slices the array texture contains.
To populate the texture, you specify which slice you're writing to with methods such as -replaceRegion:...
or -copyFrom{Buffer,Texture}:...toTexture:...
.
In a shader, you can specify which element to sample or read from using the array
parameter.
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
add a comment |
You should consider an array texture instead of a texture array. That is, a texture whose type is MTLTextureType2DArray
. You use the arrayLength
property of the texture descriptor to specify how many 2-D slices the array texture contains.
To populate the texture, you specify which slice you're writing to with methods such as -replaceRegion:...
or -copyFrom{Buffer,Texture}:...toTexture:...
.
In a shader, you can specify which element to sample or read from using the array
parameter.
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
add a comment |
You should consider an array texture instead of a texture array. That is, a texture whose type is MTLTextureType2DArray
. You use the arrayLength
property of the texture descriptor to specify how many 2-D slices the array texture contains.
To populate the texture, you specify which slice you're writing to with methods such as -replaceRegion:...
or -copyFrom{Buffer,Texture}:...toTexture:...
.
In a shader, you can specify which element to sample or read from using the array
parameter.
You should consider an array texture instead of a texture array. That is, a texture whose type is MTLTextureType2DArray
. You use the arrayLength
property of the texture descriptor to specify how many 2-D slices the array texture contains.
To populate the texture, you specify which slice you're writing to with methods such as -replaceRegion:...
or -copyFrom{Buffer,Texture}:...toTexture:...
.
In a shader, you can specify which element to sample or read from using the array
parameter.
answered Nov 16 '18 at 22:45
Ken ThomasesKen Thomases
71.9k673110
71.9k673110
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
add a comment |
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
I had considered that but then all of the source textures need to be the same size, which is not the case for me. For example, I might have an image that is 21,000 x 5,000 pixels that I'm representing with four textures of size 5,000 x 1,000 and one texture of size 1,000 x 1,000. Using a single texture is not possible because the maximum size is 16384. Smaller textures give me more granularity at determine which textures are "dirty" and who's mipmaps need to be regenerated. These textures are being filled in from an XPC service rendering arbitrary tiles.
– kennyc
Nov 17 '18 at 9:19
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
Follow Up: By reworking my tiling engine and allowing for "overflow" in tiles so that I can get tiles of a uniform size, the use if a 2D Array dramatically improves performance and cleans up the code quite a bit. The Metal docs, WWDC videos and Xcode debugging tools are pretty good, but there's still so much to learn if you're not already experienced with low-level graphics.
– kennyc
Nov 17 '18 at 22:37
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344214%2fhow-to-pass-a-variable-number-of-mtltextures-to-a-fragment-shader%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown