Opened 6 years ago

Last modified 5 years ago

#6 accepted 작업

SPIRV 리플랙션 / texture

Reported by: Hongtae Kim Owned by: Hongtae Kim
Priority: 사소 Milestone: pipelineReflection
Component: Graphics/Compute Pipeline Version: 2.0
Keywords: Cc:

Description

GLSL

vertex shader

#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUV;
layout (location = 2) in vec3 inNormal;

layout (binding = 0) uniform UBO 
{
    mat4 projection;
    mat4 model;
    vec4 viewPos;
    float lodBias;
} ubo;

layout (location = 0) out vec2 outUV;
layout (location = 1) out float outLodBias;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out vec3 outViewVec;
layout (location = 4) out vec3 outLightVec;

out gl_PerVertex 
{
    vec4 gl_Position;   
};

void main() 
{
    outUV = inUV;
    outLodBias = ubo.lodBias;

    vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0));

    gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);

    vec4 pos = ubo.model * vec4(inPos, 1.0);
    outNormal = mat3(inverse(transpose(ubo.model))) * inNormal;
    vec3 lightPos = vec3(0.0);
    vec3 lPos = mat3(ubo.model) * lightPos.xyz;
    outLightVec = lPos - pos.xyz;
    outViewVec = ubo.viewPos.xyz - pos.xyz;     
}

fragment shader

#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (binding = 1) uniform sampler2D samplerColor;

layout (location = 0) in vec2 inUV;
layout (location = 1) in float inLodBias;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inViewVec;
layout (location = 4) in vec3 inLightVec;

layout (location = 0) out vec4 outFragColor;

void main() 
{
    vec4 color = texture(samplerColor, inUV, inLodBias);

    vec3 N = normalize(inNormal);
    vec3 L = normalize(inLightVec);
    vec3 V = normalize(inViewVec);
    vec3 R = reflect(-L, N);
    vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
    float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a;

    outFragColor = vec4(diffuse * color.rgb + specular, 1.0);   
}

Change History (8)

comment:1 Changed 6 years ago by Hongtae Kim

Apple Metal

Vertex Shader

#pragma clang diagnostic ignored "-Wmissing-prototypes"

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct UBO
{
    float4x4 projection;
    float4x4 model;
    float4 viewPos;
    float lodBias;
};

struct main0_out
{
    float2 outUV [[user(locn0)]];
    float outLodBias [[user(locn1)]];
    float3 outNormal [[user(locn2)]];
    float3 outViewVec [[user(locn3)]];
    float3 outLightVec [[user(locn4)]];
    float4 gl_Position [[position]];
};

struct main0_in
{
    float3 inPos [[attribute(0)]];
    float2 inUV [[attribute(1)]];
    float3 inNormal [[attribute(2)]];
};

// Returns the determinant of a 2x2 matrix.
inline float spvDet2x2(float a1, float a2, float b1, float b2)
{
    return a1 * b2 - b1 * a2;
}

// Returns the determinant of a 3x3 matrix.
inline float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
{
    return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * spvDet2x2(a2, a3, b2, b3);
}

// Returns the inverse of a matrix, by using the algorithm of calculating the classical
// adjoint and dividing by the determinant. The contents of the matrix are changed.
float4x4 spvInverse4x4(float4x4 m)
{
    float4x4 adj;   // The adjoint matrix (inverse after dividing by determinant)

    // Create the transpose of the cofactors, as the classical adjoint of the matrix.
    adj[0][0] =  spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
    adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
    adj[0][2] =  spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]);
    adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]);

    adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
    adj[1][1] =  spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
    adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]);
    adj[1][3] =  spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]);

    adj[2][0] =  spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
    adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
    adj[2][2] =  spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]);
    adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]);

    adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
    adj[3][1] =  spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
    adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]);
    adj[3][3] =  spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]);

    // Calculate the determinant as a combination of the cofactors of the first row.
    float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]);

    // Divide the classical adjoint matrix by the determinant.
    // If determinant is zero, matrix is not invertable, so leave it unchanged.
    return (det != 0.0f) ? (adj * (1.0f / det)) : m;
}

vertex main0_out main0(main0_in in [[stage_in]], constant UBO& ubo [[buffer(0)]])
{
    main0_out out = {};
    out.outUV = in.inUV;
    out.outLodBias = ubo.lodBias;
    float3 worldPos = float3((ubo.model * float4(in.inPos, 1.0)).xyz);
    out.gl_Position = (ubo.projection * ubo.model) * float4(in.inPos, 1.0);
    float4 pos = ubo.model * float4(in.inPos, 1.0);
    float4x4 _77 = spvInverse4x4(transpose(ubo.model));
    out.outNormal = float3x3(float3(_77[0].x, _77[0].y, _77[0].z), float3(_77[1].x, _77[1].y, _77[1].z), float3(_77[2].x, _77[2].y, _77[2].z)) * in.inNormal;
    float3 lightPos = float3(0.0);
    float3 lPos = float3x3(float3(ubo.model[0].x, ubo.model[0].y, ubo.model[0].z), float3(ubo.model[1].x, ubo.model[1].y, ubo.model[1].z), float3(ubo.model[2].x, ubo.model[2].y, ubo.model[2].z)) * lightPos;
    out.outLightVec = lPos - pos.xyz;
    out.outViewVec = ubo.viewPos.xyz - pos.xyz;
    return out;
}
MTLLibrary Compilation succeeded with: 
program_source:85:12: warning: unused variable 'worldPos'
    float3 worldPos = float3((ubo.model * float4(in.inPos, 1.0)).xyz);
           ^

Fragment Shader

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct main0_out
{
    float4 outFragColor [[color(0)]];
};

struct main0_in
{
    float2 inUV [[user(locn0)]];
    float inLodBias [[user(locn1)]];
    float3 inNormal [[user(locn2)]];
    float3 inViewVec [[user(locn3)]];
    float3 inLightVec [[user(locn4)]];
};

fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> samplerColor [[texture(1)]], sampler samplerColorSmplr [[sampler(1)]])
{
    main0_out out = {};
    float4 color = samplerColor.sample(samplerColorSmplr, in.inUV, bias(in.inLodBias));
    float3 N = normalize(in.inNormal);
    float3 L = normalize(in.inLightVec);
    float3 V = normalize(in.inViewVec);
    float3 R = reflect(-L, N);
    float3 diffuse = float3(1.0) * max(dot(N, L), 0.0);
    float specular = pow(max(dot(R, V), 0.0), 16.0) * color.w;
    out.outFragColor = float4((diffuse * color.xyz) + float3(specular), 1.0);
    return out;
}

comment:2 Changed 6 years ago by Hongtae Kim

Apple Metal

MTLRenderPipelineReflection

RenderPipelineReflection: <MTLRenderPipelineReflectionInternal: 0x604000084380>
    Vertex Arguments: 
        argumentsCount = 2 
        Argument 0: <MTLBufferArgument: 0x6040000855a0>
            Name = vertexBuffer.0 
            Type = MTLArgumentTypeBuffer 
            Access = MTLArgumentAccessReadOnly 
            LocationIndex = 30 
            IsActive = 1 
            ArrayLength = 1 
            TypeInfo = 
                DataType = MTLDataTypePointer 
                ElementType = MTLDataTypeStruct  
                Access = MTLArgumentAccessReadOnly 
                Alignment = 4 
                DataSize = 32
            Alignment = 4 
            DataSize = 32 
            DataType = MTLDataTypeStruct 
        Argument 1: <MTLBufferArgument: 0x604000085aa0>
            Name = ubo 
            Type = MTLArgumentTypeBuffer 
            Access = MTLArgumentAccessReadOnly 
            LocationIndex = 0 
            IsActive = 1 
            ArrayLength = 1 
            TypeInfo = 
                DataType = MTLDataTypePointer 
                ElementType = MTLDataTypeStruct 
                ElementTypeDescription = <MTLStructTypeInternal: 0x604000244020>
                    DataType = MTLDataTypeStruct 
                    0 <MTLStructMemberInternal: 0x604000086cc0>
                        Name = projection 
                        Offset = 0 
                        DataType = MTLDataTypeFloat4x4 
                        ArgumentIndex = 0 
                        TypeInfo =  nil 
                    1 <MTLStructMemberInternal: 0x604000086090>
                        Name = model 
                        Offset = 64 
                        DataType = MTLDataTypeFloat4x4 
                        ArgumentIndex = 0 
                        TypeInfo =  nil 
                    2 <MTLStructMemberInternal: 0x604000086ef0>
                        Name = viewPos 
                        Offset = 128 
                        DataType = MTLDataTypeFloat4 
                        ArgumentIndex = 0 
                        TypeInfo =  nil 
                    3 <MTLStructMemberInternal: 0x604000087030>
                        Name = lodBias 
                        Offset = 144 
                        DataType = MTLDataTypeFloat 
                        ArgumentIndex = 0 
                        TypeInfo =  nil 
                Access = MTLArgumentAccessReadOnly 
                Alignment = 256 
                DataSize = 160
            Alignment = 256 
            DataSize = 160 
            DataType = MTLDataTypeStruct 
    Fragment Arguments: 
        argumentsCount = 2 
        Argument 0: <MTLTextureArgument: 0x604000087580>
            Name = samplerColor 
            Type = MTLArgumentTypeTexture 
            Access = MTLArgumentAccessReadOnly 
            LocationIndex = 1 
            IsActive = 1 
            ArrayLength = 1 
            TypeInfo = 
                DataType = MTLDataTypeTexture 
                TextureDataType = MTLDataTypeFloat 
                TextureType = MTLTextureType2D 
                Access = MTLArgumentAccessReadOnly 
                IsDepthTexture = 0
            TextureType = MTLTextureType2D 
            TextureDataType = MTLDataTypeFloat 
            IsDepthTexture = 0 
        Argument 1: <MTLArgumentInternal: 0x604000272380>
            Name = samplerColorSmplr 
            Type = MTLArgumentTypeSampler 
            Access = MTLArgumentAccessReadOnly 
            LocationIndex = 1 
            IsActive = 1 
            ArrayLength = 1

comment:3 Changed 6 years ago by Hongtae Kim

DKGL (mac)

Vertex Stage-Input Attributes

TestApp1_macOS[85247:19036511] [V] VertexFunction.VertexAttributes: 3
TestApp1_macOS[85247:19036511] [V]   --> VertexAttribute[0]: "inPos" (location:0)
TestApp1_macOS[85247:19036511] [V]   --> VertexAttribute[1]: "inUV" (location:1)
TestApp1_macOS[85247:19036511] [V]   --> VertexAttribute[2]: "inNormal" (location:2)

PipelineReflection?

TestApp1_macOS[85247:19036511] [V] PipelineReflection.VertexResources: 1
TestApp1_macOS[85247:19036511] [I] ShaderResource: ubo (set=0, binding=0)
TestApp1_macOS[85247:19036511] [I]  +Type:Buffer, Access:ReadOnly, Enabled:1 Alignment:256, Size:160
TestApp1_macOS[85247:19036511] [I]  +TypeKey: ubo (struct)
TestApp1_macOS[85247:19036511] [I]      + projection (Float4x4, Offset: 0, Size: 24640)
TestApp1_macOS[85247:19036511] [I]      + model (Float4x4, Offset: 64, Size: 24640)
TestApp1_macOS[85247:19036511] [I]      + viewPos (Float4, Offset: 128, Size: 24640)
TestApp1_macOS[85247:19036511] [I]      + lodBias (Float, Offset: 144, Size: 24640)
TestApp1_macOS[85247:19036511] [V] PipelineReflection.FragmentResources: 2
TestApp1_macOS[85247:19036511] [I] ShaderResource: samplerColor (set=0, binding=1)
TestApp1_macOS[85247:19036511] [I]  +Type:Texture, Access:ReadOnly, Enabled:1 Alignment:494728, Size:24640
TestApp1_macOS[85247:19036511] [I] ShaderResource: samplerColorSmplr (set=0, binding=1)
TestApp1_macOS[85247:19036511] [I]  +Type:Sampler, Access:ReadOnly, Enabled:1 Alignment:494728, Size:24640

comment:4 Changed 6 years ago by Hongtae Kim

DKGL (windows)

Vertex Stage-Input Attributes

[35228:47172 V] VertexFunction.VertexAttributes: 3
[35228:47172 V]   --> VertexAttribute[0]: "inUV" (location:1)
[35228:47172 V]   --> VertexAttribute[1]: "inPos" (location:0)
[35228:47172 V]   --> VertexAttribute[2]: "inNormal" (location:2)

PipelineReflection?

[35228:47172 V] PipelineReflection.VertexResources: 1
[35228:47172 I] ShaderResource: ubo (set=0, binding=0)
[35228:47172 I]  +Type:Buffer, Access:ReadOnly, Enabled:1 Alignment:0, Size:148
[35228:47172 I]  +TypeKey: ubo (struct)
[35228:47172 I]      + projection (Float4x4, Offset: 0, Size: 64)
[35228:47172 I]      + model (Float4x4, Offset: 64, Size: 64)
[35228:47172 I]      + viewPos (Float4, Offset: 128, Size: 16)
[35228:47172 I]      + lodBias (Float, Offset: 144, Size: 4)
[35228:47172 V] PipelineReflection.FragmentResources: 1
[35228:47172 I] ShaderResource: samplerColor (set=0, binding=1)
[35228:47172 I]  +Type:Texture, Access:ReadOnly, Enabled:1 Alignment:0, Size:0

comment:5 Changed 6 years ago by Hongtae Kim

VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 는 Apple Metal 에서 어떻게 처리를 해야 하나..

comment:6 Changed 6 years ago by Hongtae Kim

https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkDescriptorSetLayoutCreateInfo.html

The VkDescriptorSetLayoutBinding::binding members of the elements of the pBindings array must each have different values.

https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf (page 62)

  • Vulkan 에서는 VkDescriptorType? 과 관계없이 binding 은 고유해야 함.
  • Apple Metal 에서는 buffer, sampler, texture 타입 내에서만 고유해야 함. 서로 다른 타입이면 index 가 중복이 가능.

TODO

Metal 에서 중복된 인덱스의 Sampler / Texture 경우엔 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 으로 처리

ticket:8

comment:7 Changed 5 years ago by Hongtae Kim

DKShaderResource::TypeSampledTexture? 타입 추가.

Metal 에서는 sampler 와 texture 가 동일한 binding 일 경우에 COMBINED_IMAGE_SAMPLER (SampledImage?) 로 간주.

comment:8 Changed 5 years ago by Hongtae Kim

Priority: 치명적사소
Status: assignedaccepted
Note: See TracTickets for help on using tickets.