在金属着色语言中创建全局可访问的常量缓冲区 [英] Creating globally accessible constant buffer in Metal Shading Language

查看:100
本文介绍了在金属着色语言中创建全局可访问的常量缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我有一个关于Metal中的常量缓冲区的问题. 假设我有类似的东西:


I've got a question about constant buffers in Metal. Let's assume, that I've got something like:

...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]]仅用于自变量).有什么窍门吗?

Is it possible to call CalcSomething() without passing ANY_VALUE as input argument?
For example in DX11 or in OpenGL you create constant buffer, which can be accessed from every place in shader code.

I think about copying content of "cb" to temporary global object but I have no idea how to do it (because of constant address space).

Another idea is to somehow declare "cb" in global scope (but unfortunately [[buffer]] is designed only for arguments). Is there any trick for that?

推荐答案

我的问题的解决方案:

Solution to my issue:

#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的一部分,我使用了宏:

I create one struct which contains my whole original shader. Arguments are passed as references to the constructor. Any function can read from constant buffer without receiving tons of arguments. To fix problem with ANY_VALUE which is now part of cb I use macro:

#define ANY_VALUE cb.ANY_VALUE.

这篇关于在金属着色语言中创建全局可访问的常量缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆