在Metal Shading Language中创建全局可访问的常量缓冲区

时间:2015-08-21 08:32:01

标签: ios metal

我对Metal中的常量缓冲区有疑问。 让我们假设,我有类似的东西:

...list of includes goes here...

using namespace metal; 

struct ConstantBuffer {
     float ANY_VALUE;
};

struct VS_INPUTS { 
    float4 i_pos_ms [ [ attribute ( 0 ) ] ] ; 
} ; 

struct V2P_STRUCT { 
    float4 v_pos_out [ [ position ] ] ;  
} ; 

float3 CalcSomething() {
    return float3(ANY_VALUE, ANY_VALUE, ANY_VALUE); // !!!!!!!!
}

vertex V2P_STRUCT VertexFunc(VS_INPUTS vs_inputs [ [ stage_in ] ] , 
                             constant ConstantBuffer& cb [ [ buffer (1) ] ] )
{
    V2P_STRUCT vs_outputs;

    vs_outputs.v_pos_out.xyz = CalcSomething();
    vs_outputs.v_pos_out.w = cb.ANY_VALUE; // that's OK

    return vs_outputs;
}

是否可以在不传递ANY_VALUE作为输入参数的情况下调用CalcSomething()?
例如,在DX11或OpenGL中,您可以创建常量缓冲区,可以从着色器代码中的每个位置访问该缓冲区。

我想将“cb”的内容复制到临时全局对象,但我不知道怎么做(因为地址空间不变)。

另一个想法是以某种方式在全局范围内声明“cb”(但不幸的是[[buffer]]仅为参数设计)。这有什么诀窍吗?

2 个答案:

答案 0 :(得分:5)

解决我的问题:

#include <metal_stdlib> 
#include <metal_graphics> 
#include <metal_texture> 
#include <metal_matrix> 
#include <metal_math> 
#include <metal_geometric> 
#include <metal_common> 

using namespace metal; 

constant float MyVariable = 4;

struct ConstantBuffer 
{
    float ANY_VALUE;
};

struct VS_INPUTS { 
    float4 i_pos_ms [ [ attribute ( 0 ) ] ] ; 
}; 

struct V2P_STRUCT { 
    float4 v_pos_out [ [ position ] ] ;  
}; 

struct VertexShader 
{
    thread VS_INPUTS& vs_inputs;
    thread texture2d<float> img;

    constant ConstantBuffer& cb;

    VertexShader(thread VS_INPUTS& inputs, constant ConstantBuffer& b, thread texture2d<float>& texture) 
        : cb(b) 
        , vs_inputs(inputs)
        , img(texture)
    {}

    float3 CalcSomething() {
        return float3(cb.ANY_VALUE, cb.ANY_VALUE, cb.ANY_VALUE); // !!!!!!!!
    }

    V2P_STRUCT majn()
    { 
        V2P_STRUCT vs_outputs;

        vs_outputs.v_pos_out.xyz = CalcSomething();
        vs_outputs.v_pos_out.w = cb.ANY_VALUE * vs_inputs.i_pos_ms.x * MyVariable; // that's OK

        return vs_outputs;
    }
};

vertex V2P_STRUCT VertexFunc(VS_INPUTS vs_inputs [ [ stage_in ] ] , 
                         constant ConstantBuffer& cb [ [ buffer (1) ] ] ,
                         texture2d<float> img [[ texture(0) ]]
                         )
{
    VertexShader vs(vs_inputs, cb, img);
    return vs.majn();
}

我创建了一个包含我整个原始着色器的结构。参数作为对构造函数的引用传递。任何函数都可以从常量缓冲区读取而不会接收大量参数。 要修复ANY_VALUE的问题,它现在是cb的一部分,我使用宏:

#define ANY_VALUE cb.ANY_VALUE.

答案 1 :(得分:1)

这里有很多问题。我认为最好是你为我们提供了一个需要解决的问题,而不是试图将其他平台的概念变成金属。现在,这里有一些想法。

是否可以在不传递ANY_VALUE作为输入参数的情况下调用CalcSomething()?

struct ConstantBuffer {
   const float ANY_VALUE;
};
constant const ConstantBuffer constantBuffer = {1};

static float3 CalcSomething() {
    return float3(constantBuffer.ANY_VALUE);
}

你确定CalcSomething不应该是一种方法吗?

struct ConstantBuffer {
   ConstantBuffer(const float value): value(value) {}

   float3 calculateSomething() const {
      return float3(value);
   }

   const float value;
};

vertex V2P_STRUCT VertexFunc(
   constant const ConstantBuffer& _constantBuffer [[buffer(1)]]
) {
   // Metal can't currently deal with methods without this.
   const auto constantBuffer = _constantBuffer;

另一个想法是以某种方式在全局范围内声明“cb”(但不幸的是[[buffer]]仅为参数设计)。有什么诀窍吗?

在我看来,“技巧”是用Swift创建缓冲区,而不是Metal着色语言。