Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port from main to RB-2.1 - Adds Metal Support to ociodisplay and enables running GPU tests with Metal backend (#1538) #1559

Merged
merged 2 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions src/OpenColorIO/GpuShaderClassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
namespace OCIO_NAMESPACE
{

std::string GetArrayLengthVariableName(const std::string& variableName)
{
return variableName + "_count";
}

std::string MetalShaderClassWrapper::generateClassWrapperHeader(GpuShaderText& kw) const
{
if(m_className.empty())
Expand All @@ -27,7 +32,11 @@ std::string MetalShaderClassWrapper::generateClassWrapperHeader(GpuShaderText& k
std::string separator = "";
for(const auto& param : m_functionParameters)
{
kw.newLine() << separator << param.type << " " << param.name;
kw.newLine() << separator << (param.m_isArray ? "constant " : "") << param.m_type << " " << param.m_name;
if(param.m_isArray)
{
kw.newLine() << ", int " << GetArrayLengthVariableName(param.m_name.substr(0, param.m_name.find('[')));
}
separator = ", ";
}
kw.dedent();
Expand All @@ -37,21 +46,35 @@ std::string MetalShaderClassWrapper::generateClassWrapperHeader(GpuShaderText& k
kw.indent();
for(const auto& param : m_functionParameters)
{
size_t openAngledBracketPos = param.name.find('[');
bool isArray = openAngledBracketPos != std::string::npos;
if(!isArray)
kw.newLine() << "this->" << param.name << " = " << param.name << ";";
size_t openAngledBracketPos = param.m_name.find('[');
if(!param.m_isArray)
{
kw.newLine() << "this->" << param.m_name << " = " << param.m_name << ";";
}
else
{
size_t closeAngledBracketPos = param.name.find(']');
std::string variableName = param.name.substr(0, openAngledBracketPos);
size_t closeAngledBracketPos = param.m_name.find(']');
std::string variableName = param.m_name.substr(0, openAngledBracketPos);

kw.newLine() << "for(int i = 0; i < "
<< param.name.substr(openAngledBracketPos+1, closeAngledBracketPos-openAngledBracketPos-1)
<< GetArrayLengthVariableName(variableName)
<< "; ++i)";
kw.newLine() << "{";
kw.indent();
kw.newLine() << "this->" << variableName << "[i] = " << variableName << "[i];";
kw.dedent();
kw.newLine() << "}";

kw.newLine() << "for(int i = "
<< GetArrayLengthVariableName(variableName)
<< "; i < "
<< param.m_name.substr(openAngledBracketPos+1, closeAngledBracketPos-openAngledBracketPos-1)
<< "; ++i)";
kw.newLine() << "{";
kw.indent();
kw.newLine() << "this->" << variableName << "[i] = 0;";
kw.dedent();
kw.newLine() << "}";
}
}
kw.dedent();
Expand Down Expand Up @@ -79,7 +102,11 @@ std::string MetalShaderClassWrapper::generateClassWrapperFooter(GpuShaderText& k
std::string separator = "";
for(const auto& param : m_functionParameters)
{
kw.newLine() << separator << param.type << " " << param.name;
kw.newLine() << separator << (param.m_isArray ? "constant " : "") << param.m_type << " " << param.m_name;
if(param.m_isArray)
{
kw.newLine() << ", int " << GetArrayLengthVariableName(param.m_name.substr(0, param.m_name.find('[')));
}
separator = ", ";
}
kw.newLine() << separator << kw.float4Keyword() << " inPixel)";
Expand All @@ -92,13 +119,18 @@ std::string MetalShaderClassWrapper::generateClassWrapperFooter(GpuShaderText& k
separator = "";
for(const auto& param : m_functionParameters)
{
size_t openAngledBracketPos = param.name.find('[');
size_t openAngledBracketPos = param.m_name.find('[');
bool isArray = openAngledBracketPos != std::string::npos;

if(!isArray)
kw.newLine() << separator << param.name;
{
kw.newLine() << separator << param.m_name;
}
else
kw.newLine() << separator << param.name.substr(0, openAngledBracketPos);
{
kw.newLine() << separator << param.m_name.substr(0, openAngledBracketPos);
kw.newLine() << ", " << GetArrayLengthVariableName(param.m_name.substr(0, openAngledBracketPos));
}
separator = ", ";
}
kw.dedent();
Expand Down
11 changes: 7 additions & 4 deletions src/OpenColorIO/GpuShaderClassWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,16 @@ class MetalShaderClassWrapper : public GpuShaderClassWrapper
struct FunctionParam
{
FunctionParam(const std::string& type, const std::string& name) :
type(type),
name(name)
m_type(type),
m_name(name)
{
size_t openAngledBracketPos = name.find('[');
m_isArray = openAngledBracketPos != std::string::npos;
}

std::string type;
std::string name;
std::string m_type;
std::string m_name;
bool m_isArray;
};

std::string getClassWrapperName(const std::string &resourcePrefix, const std::string& functionName);
Expand Down
10 changes: 10 additions & 0 deletions src/OpenColorIO/GpuShaderUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,16 @@ std::string GpuShaderText::declareVarStr(const std::string & name, float v)
return floatDecl(name) + " = " + getFloatString(v, m_lang);
}

std::string GpuShaderText::vectorCompareExpression(const std::string& lhs, const std::string& op, const std::string& rhs)
{
std::string ret = lhs + " " + op + " " + rhs;
if(m_lang == GPU_LANGUAGE_MSL_2_0)
{
ret = "any( " + ret + " )";
}
return ret;
}

void GpuShaderText::declareVarConst(const std::string & name, bool v)
{
newLine() << constKeyword() << declareVarStr(name, v) << ";";
Expand Down
2 changes: 2 additions & 0 deletions src/OpenColorIO/GpuShaderUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class GpuShaderText
std::string intKeyword() const;

std::string colorDecl(const std::string& name) const;

std::string vectorCompareExpression(const std::string& lhs, const std::string& op, const std::string& rhs);

//
// Scalar & arrays helper functions.
Expand Down
12 changes: 6 additions & 6 deletions src/OpenColorIO/ops/gradingprimary/GradingPrimaryOpGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void AddGPLogForwardShader(GpuShaderCreatorRcPtr & shaderCreator,
<< " + " << props.pivot << ";";

// Not sure if the if helps performance, but it does allow out == in at the default values.
st.newLine() << "if ( " << props.gamma << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.gamma, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();
st.newLine() << st.float3Decl("normalizedOut")
Expand Down Expand Up @@ -206,7 +206,7 @@ void AddGPLogInverseShader(GpuShaderCreatorRcPtr & shaderCreator,
st.newLine() << "}";

// Not sure if the if helps performance, but it does allow out == in at the default values.
st.newLine() << "if ( " << props.gamma << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.gamma, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();
st.newLine() << st.float3Decl("normalizedOut")
Expand Down Expand Up @@ -307,7 +307,7 @@ void AddGPLinForwardShader(GpuShaderCreatorRcPtr & shaderCreator,

// Not sure if the if helps performance, but it does allow out == in at the default values.
// Although note that the log-to-lin in Tone Op also prevents out == in.
st.newLine() << "if ( " << props.contrast << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.contrast, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();

Expand Down Expand Up @@ -345,7 +345,7 @@ void AddGPLinInverseShader(GpuShaderCreatorRcPtr & shaderCreator,

// Not sure if the if helps performance, but it does allow out == in at the default values.
// Although note that the log-to-lin in Tone Op also prevents out == in.
st.newLine() << "if ( " << props.contrast << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.contrast, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();
// NB: The sign(outColor.rgb) is a vec3, preserving the sign of each channel.
Expand Down Expand Up @@ -446,7 +446,7 @@ void AddGPVideoForwardShader(GpuShaderCreatorRcPtr & shaderCreator,
<< " + " << props.pivotBlack << ";";

// Not sure if the if helps performance, but it does allow out == in at the default values.
st.newLine() << "if ( " << props.gamma << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.gamma, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();
st.newLine() << st.float3Decl("normalizedOut")
Expand Down Expand Up @@ -486,7 +486,7 @@ void AddGPVideoInverseShader(GpuShaderCreatorRcPtr & shaderCreator,
st.newLine() << "}";

// Not sure if the if helps performance, but it does allow out == in at the default values.
st.newLine() << "if ( " << props.gamma << " != " << st.float3Const(1.f) << " )";
st.newLine() << "if ( " << st.vectorCompareExpression(props.gamma, "!=", st.float3Const(1.f)) << " )";
st.newLine() << "{";
st.indent();
st.newLine() << st.float3Decl("normalizedOut")
Expand Down
34 changes: 31 additions & 3 deletions src/apps/ociodisplay/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ namespace OCIO = OCIO_NAMESPACE;
#include <GL/gl.h>
#include <GL/glut.h>
#endif

#if __APPLE__
#include "metalapp.h"
#endif
#include "glsl.h"
#include "oglapp.h"

bool g_verbose = false;
bool g_gpulegacy = false;
bool g_gpuinfo = false;
#if __APPLE__
bool g_useMetal = false;
#endif

std::string g_filename;

Expand Down Expand Up @@ -414,7 +419,12 @@ void UpdateOCIOGLState()

// Set the shader context.
OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();
shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
shaderDesc->setLanguage(
#if __APPLE__
g_useMetal ?
OCIO::GPU_LANGUAGE_MSL_2_0 :
#endif
OCIO::GPU_LANGUAGE_GLSL_1_2);
shaderDesc->setFunctionName("OCIODisplay");
shaderDesc->setResourcePrefix("ocio_");

Expand Down Expand Up @@ -613,6 +623,12 @@ void parseArguments(int argc, char **argv)
{
g_gpuinfo = true;
}
#if __APPLE__
else if(0==strcmp(argv[i], "-metal"))
{
g_useMetal = true;
}
#endif
else if(0==strcmp(argv[i], "-h"))
{
std::cout << std::endl;
Expand All @@ -624,6 +640,9 @@ void parseArguments(int argc, char **argv)
std::cout << " -v : displays the color space information" << std::endl;
std::cout << " -gpulegacy : use the legacy (i.e. baked) GPU color processing" << std::endl;
std::cout << " -gpuinfo : output the OCIO shader program" << std::endl;
#if __APPLE__
std::cout << " -metal : use metal OCIO shader backend " << std::endl;
#endif
std::cout << std::endl;
exit(0);
}
Expand All @@ -640,7 +659,16 @@ int main(int argc, char **argv)

try
{
g_oglApp = std::make_shared<OCIO::ScreenApp>("ociodisplay", 512, 512);
#if __APPLE__
if(g_useMetal)
{
g_oglApp = std::make_shared<OCIO::MetalApp>("ociodisplay", 512, 512);
}
else
#endif
{
g_oglApp = std::make_shared<OCIO::ScreenApp>("ociodisplay", 512, 512);
}
}
catch (const OCIO::Exception & e)
{
Expand Down
26 changes: 26 additions & 0 deletions src/libutils/oglapphelpers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ set(INCLUDES
oglapp.h
)

if(APPLE)

list(APPEND SOURCES
msl.mm
mtltexture.mm
metalapp.mm
)

list(APPEND INCLUDES
msl.h
mtltexture.h
metalapp.h
)

endif()

add_library(oglapphelpers STATIC ${SOURCES})
set_target_properties(oglapphelpers PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(oglapphelpers PROPERTIES OUTPUT_NAME OpenColorIOoglapphelpers)
Expand Down Expand Up @@ -82,6 +98,16 @@ else()
)
endif()

if(APPLE)
target_link_libraries(oglapphelpers
PRIVATE
"-framework Carbon"
"-framework IOKit"
"-framework Metal"
"-framework CoreVideo"
)
endif()

if(${OCIO_EGL_HEADLESS})
target_include_directories(oglapphelpers
PRIVATE
Expand Down
6 changes: 3 additions & 3 deletions src/libutils/oglapphelpers/glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ std::string OpenGLBuilder::getGLSLVersionString()
switch (m_shaderDesc->getLanguage())
{
case GPU_LANGUAGE_GLSL_1_2:
case GPU_LANGUAGE_MSL_2_0:
// That's the minimal version supported.
return "#version 120";
case GPU_LANGUAGE_GLSL_1_3:
Expand All @@ -460,15 +461,14 @@ std::string OpenGLBuilder::getGLSLVersionString()
case GPU_LANGUAGE_CG:
case GPU_LANGUAGE_HLSL_DX11:
case LANGUAGE_OSL_1:
case GPU_LANGUAGE_MSL_2_0:
default:
// These are all impossible in OpenGL contexts.
// The shader will be unusable, so let's throw
throw Exception("Invalid shader language for OpenGLBuilder");
}
}

unsigned OpenGLBuilder::buildProgram(const std::string & clientShaderProgram)
unsigned OpenGLBuilder::buildProgram(const std::string & clientShaderProgram, bool standaloneShader)
{
const std::string shaderCacheID = m_shaderDesc->getCacheID();
if(shaderCacheID!=m_shaderCacheID)
Expand All @@ -481,7 +481,7 @@ unsigned OpenGLBuilder::buildProgram(const std::string & clientShaderProgram)

std::ostringstream os;
os << getGLSLVersionString() << std::endl
<< m_shaderDesc->getShaderText() << std::endl
<< (!standaloneShader ? m_shaderDesc->getShaderText() : "") << std::endl
<< clientShaderProgram << std::endl;

if(m_verbose)
Expand Down
2 changes: 1 addition & 1 deletion src/libutils/oglapphelpers/glsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class OpenGLBuilder

// Build the complete shader program which includes the OCIO shader program
// and the client shader program.
unsigned buildProgram(const std::string & clientShaderProgram);
unsigned buildProgram(const std::string & clientShaderProgram, bool standaloneShader);
void useProgram();
unsigned getProgramHandle();

Expand Down
Loading