Using 3D Texture on Metal

Hello everyone, I'm graphic beginner programmer

I want to use 3d texture on metal for my projects...
But I can't, because of error.
I try example of this link..

fragment half4 mip_fragment 
( 
VertexOutput in [[ stage_in ]],
texture2d<float> backface [[ texture(0) ]],
texture3d<float> volume [[ texture(1) ]]
)
{
  constexpr sampler s(s_address::clamp_to_edge, t_address::clamp_to_edge, min_filter::linear, mag_filter::linear);
    float3 rgb = backface.sample(s, in.pixelCoord).rgb;
    float3 lookupColor = volume.sample(s, rgb, 0).rgb;
    return half4(half3(lookupColor), 1.h);
}

But I get this errors. Fragment Function(mip_fragment): incorrect type of texture (MTLTextureType2D) bound at texture binding at index 1 (expect MTLTextureType3D) for volume[0].

And app is crashed. Please help me.

Can you share more of your code? You are hitting a Metal validation error, meaning something is wrong in your CPU code, not the shader. Please share the code where you create the textures and where you bind your textures to the command encoder.

Ok I render metal shader from scenekit using scntechnique, It's all of my setting

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>passes</key>
	<dict>
		<key>pass_backface</key>
		<dict>
			<key>metalVertexShader</key>
			<string>backface_vertex</string>
			<key>metalFragmentShader</key>
			<string>backface_fragment</string>
			<key>program</key>
			<string>doesntexist</string>
			<key>depthStates</key>
			<dict>
				<key>clear</key>
				<true/>
			</dict>
			<key>colorStates</key>
			<dict>
				<key>clear</key>
				<true/>
				<key>clearColor</key>
				<string>sceneBackground</string>
			</dict>
			<key>cullMode</key>
			<string>front</string>
			<key>includeCategoryMask</key>
			<string>2</string>
			<key>draw</key>
			<string>DRAW_NODE</string>
			<key>inputs</key>
			<dict>
				<key>aPos</key>
				<string>vertex-symbol</string>
			</dict>
			<key>outputs</key>
			<dict>
				<key>color</key>
				<string>backface</string>
			</dict>
		</dict>
		<key>pass_mip</key>
		<dict>
			<key>colorStates</key>
			<dict>
				<key>clear</key>
				<true/>
				<key>clearColor</key>
				<string>sceneBackground</string>
			</dict>
			<key>depthStates</key>
			<dict>
				<key>clear</key>
				<true/>
			</dict>
			<key>metalVertexShader</key>
			<string>mip_vertex</string>
			<key>metalFragmentShader</key>
			<string>mip_fragment</string>
			<key>program</key>
			<string>doesntexist</string>
			<key>cullMode</key>
			<string>back</string>
			<key>includeCategoryMask</key>
			<string>2</string>
			<key>draw</key>
			<string>DRAW_NODE</string>
			<key>inputs</key>
			<dict>
				<key>aPos</key>
				<string>vertex-symbol</string>
				<key>viewport</key>
				<string>screen_size</string>
				<key>backface</key>
				<string>backface</string>
				<key>volume</key>
				<string>volume</string>
			</dict>
			<key>outputs</key>
			<dict>
				<key>color</key>
				<string>COLOR</string>
				<key>depth</key>
				<string>DEPTH</string>
			</dict>
		</dict>
	</dict>
	<key>sequence</key>
	<array>
		<string>pass_backface</string>
		<string>pass_mip</string>
	</array>
	<key>targets</key>
	<dict>
		<key>backface</key>
		<dict>
			<key>type</key>
			<string>color</string>
		</dict>
	</dict>
	<key>symbols</key>
	<dict>
		<key>vertex-symbol</key>
		<dict>
			<key>semantic</key>
			<string>vertex</string>
		</dict>
		<key>screen_size</key>
		<dict>
			<key>type</key>
			<string>vec2</string>
		</dict>
		<key>volume</key>
		<dict>
			<key>type</key>
			<string>sampler3D</string>
		</dict>
	</dict>
</dict>
</plist>

And, it's my metal shader code

#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>

struct VertexInput
{
  float3 position [[ attribute(SCNVertexSemanticPosition) ]];
  float2 uv [[attribute(SCNVertexSemanticTexcoord0)]];
};

struct NodeBuffer {
  float4x4 modelTransform;
  float4x4 modelViewTransform;
  float4x4 normalTransform;
  float4x4 modelViewProjectionTransform;
  float2x3 boundingBox;
};

struct VertexOutput
{
  float4 position [[position]];
  float2 pixelCoord;
  float3 color;
};

vertex VertexOutput backface_vertex(
  VertexInput in [[ stage_in ]]
  , constant SCNSceneBuffer& scn_frame [[buffer(0)]]
  , constant NodeBuffer& scn_node [[buffer(1)]])
{
  VertexOutput out;
  out.position = scn_node.modelViewProjectionTransform
    * float4(in.position, 1.0);
  out.color = out.position.xyz;
  return out;
}

fragment float4 backface_fragment(VertexOutput in [[stage_in]])
{
  float4 color = float4(in.color, 1.0);
  return color;
}

struct MipUniforms
{
  float2 viewport;
};

vertex VertexOutput mip_vertex
(
  VertexInput in [[ stage_in ]]
  , constant SCNSceneBuffer& scn_frame [[buffer(0)]]
  , constant NodeBuffer& scn_node [[buffer(1)]]
  , constant MipUniforms& uniforms [[buffer(2)]]
)
{
  VertexOutput out;
  out.position = scn_node.modelViewProjectionTransform
    * float4(in.position, 1.0);
  out.color = out.position.xyz;
   
  float2 viewport = uniforms.viewport;
  out.pixelCoord = (in.position.xy - viewport * 0.5) / viewport;
  return out;
}

fragment half4 mip_fragment ( VertexOutput in [[ stage_in ]],
               texture2d<float> backface [[ texture(0) ]],
               texture3d<float> volume [[ texture(1) ]]
               )
{
  constexpr sampler s(s_address::clamp_to_edge, t_address::clamp_to_edge, min_filter::linear, mag_filter::linear);
  float3 rgb = backface.sample(s, in.pixelCoord).rgb;
  float3 lookupColor = volume.sample(s, rgb, 0).rgb;
  return half4(half3(lookupColor), 1.h);
}

And then I will set 3d texture at runtime. So first time, 3d texture named volume is not set yet.

Accepted Answer

When you bind your texture to index texture(1), what does your code look like? For example:

// The following texture object is a MTLTextureType3D and will be bound to index 1
// id <MTLTexture> myTexture3D;
[renderEncoder setFragmentTexture:myTexture3D atIndex:1];

OK, so I think the issue is that sampler3D is not a supported type as listed in Table 4 according to the SCNTechnique documentation. I'll update this post if I can verify there isn't a way around that (My guess is no, unfortunately).

Using 3D Texture on Metal
 
 
Q