Skip to content
Open
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
11 changes: 11 additions & 0 deletions src/OpenColorIO/GpuShaderUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,17 @@ std::string GpuShaderText::intKeyword() const
return "int";
}

std::string GpuShaderText::intCast(const std::string & expr) const
{
// HLSL/DXC flags the functional cast int(x) under -Wfloat-conversion; a C-style cast suppresses it (GLSL forbids C-style casts).
if (m_lang == GPU_LANGUAGE_HLSL_SM_5_0)
{
return "(int)(" + expr + ")";
}

return intKeyword() + "(" + expr + ")";
}

std::string GpuShaderText::intKeywordConst() const
{
std::string str;
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 intKeywordConst() const;
std::string intDecl(const std::string& name) const;
// Cast a float expression to int using language-appropriate syntax.
std::string intCast(const std::string& expr) const;

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

Expand Down
22 changes: 10 additions & 12 deletions src/OpenColorIO/ops/fixedfunction/FixedFunctionOpGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void Add_hue_weight_shader(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText
// << " hue = mix( hue, hue - 6.28318530717959, step( 3.14159265358979, hue));\n"

ss.newLine() << ss.floatDecl("knot_coord") << " = clamp(2. + hue * float(" << inv_width << "), 0., 4.);";
ss.newLine() << "int j = int(min(knot_coord, 3.));";
ss.newLine() << "int j = " << ss.intCast("min(knot_coord, 3.)") << ";";
ss.newLine() << ss.floatDecl("t") << " = knot_coord - float(j);";
ss.newLine() << ss.float4Decl("monomials") << " = " << ss.float4Const("t*t*t", "t*t", "t", "1.") << ";";
ss.newLine() << ss.float4Decl("m0") << " = " << ss.float4Const(0.25, 0.00, 0.00, 0.00) << ";";
Expand Down Expand Up @@ -867,14 +867,14 @@ std::string _Add_Cusp_table(
ss.newLine() << "{";
ss.indent();

ss.newLine() << ss.intDecl("i") << " = " << ss.intKeyword() << "(h) + " << g.gamut_cusp_table.base_index << ";";
ss.newLine() << ss.intDecl("i") << " = " << ss.intCast("h") << " + " << g.gamut_cusp_table.base_index << ";";

ss.newLine() << ss.intDecl("i_lo") << " = " << ss.intKeyword() << "(max("
<< ss.floatKeyword() << "(" << g.gamut_cusp_table.lower_wrap_index << "), "
<< ss.floatKeyword() << "(i + " << g.hue_linearity_search_range[0] << ")));";
ss.newLine() << ss.intDecl("i_hi") << " = " << ss.intKeyword() << "(min("
<< ss.floatKeyword() << "(" << g.gamut_cusp_table.upper_wrap_index << "), "
<< ss.floatKeyword() << "(i + " << g.hue_linearity_search_range[1] << ")));";
ss.newLine() << ss.intDecl("i_lo") << " = " << ss.intCast(
"max(" + ss.floatKeyword() + "(" + std::to_string(g.gamut_cusp_table.lower_wrap_index) + "), "
+ ss.floatKeyword() + "(i + " + std::to_string(g.hue_linearity_search_range[0]) + "))") << ";";
ss.newLine() << ss.intDecl("i_hi") << " = " << ss.intCast(
"min(" + ss.floatKeyword() + "(" + std::to_string(g.gamut_cusp_table.upper_wrap_index) + "), "
+ ss.floatKeyword() + "(i + " + std::to_string(g.hue_linearity_search_range[1]) + "))") << ";";

ss.newLine() << "while (i_lo + 1 < i_hi)";
ss.newLine() << "{";
Expand Down Expand Up @@ -1583,8 +1583,7 @@ void Add_Gamut_Compress_Fwd_Shader(
const std::string reachName = _Add_Reach_table(shaderCreator, resourceIndex, s.reach_m_table);

_Add_WrapHueChannel_Shader(shaderCreator, ss);
_Add_SinCos_Shader(shaderCreator, ss);

// No _Add_SinCos_Shader: gamut-compress stays in JMh space, so cos_hr/sin_hr would be unused.
ss.newLine() << ss.floatDecl("reachMaxM") << " = " << reachName << "_sample(" << pxl << ".b);";

_Add_Gamut_Compress_Fwd_Shader(shaderCreator, ss, resourceIndex, s, g);
Expand Down Expand Up @@ -1626,8 +1625,7 @@ void Add_Gamut_Compress_Inv_Shader(
const std::string reachName = _Add_Reach_table(shaderCreator, resourceIndex, s.reach_m_table);

_Add_WrapHueChannel_Shader(shaderCreator, ss);
_Add_SinCos_Shader(shaderCreator, ss);

// No _Add_SinCos_Shader: gamut-compress stays in JMh space, so cos_hr/sin_hr would be unused.
ss.newLine() << ss.floatDecl("reachMaxM") << " = " << reachName << "_sample(" << pxl << ".b);";

_Add_Gamut_Compress_Inv_Shader(shaderCreator, ss, resourceIndex, s, g);
Expand Down
3 changes: 2 additions & 1 deletion src/OpenColorIO/ops/gradingrgbcurve/GradingBSplineCurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,8 @@ void GradingBSplineCurveImpl::AddShaderEvalRevHue(GpuShaderText & st,
st.newLine() << "float knStart = " << knots << "[knotsOffs];";
st.newLine() << "float knEnd = " << knots << "[knotsOffs + knotsCnt - 1];";
st.newLine() << "float knStartY = " << coefs << "[coefsOffs + coefsSets * 2];";
// HUE-FX (curve 7): offset start Y bound by its knot, matching CPU evalRevHue.
st.newLine() << "knStartY = (curveIdx == 7) ? knStartY + knStart : knStartY;";
st.newLine() << "float knEndY;";
st.newLine() << "{";
st.newLine() << " float A = " << coefs << "[coefsOffs + coefsSets - 1];";
Expand All @@ -1198,7 +1200,6 @@ void GradingBSplineCurveImpl::AddShaderEvalRevHue(GpuShaderText & st,
st.newLine() << " float kn = " << knots << "[knotsOffs + knotsCnt - 2];";
st.newLine() << " float t = knEnd - kn;";
st.newLine() << " knEndY = ( A * t + B ) * t + C;";
// The HUE-FX curve is index 7 and requires special handling.
st.newLine() << " knEndY = (curveIdx == 7) ? knEndY + knEnd : knEndY;";
st.newLine() << "}";

Expand Down
27 changes: 16 additions & 11 deletions src/OpenColorIO/ops/gradingrgbcurve/GradingRGBCurveOpGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,22 @@ void AddCurveEvalMethodTextToShaderProgram(GpuShaderCreatorRcPtr & shaderCreator
}

st.newLine() << "";
if (shaderCreator->getLanguage() == LANGUAGE_OSL_1 || shaderCreator->getLanguage() == GPU_LANGUAGE_MSL_2_0)
const bool inverse = gcData->getDirection() == TRANSFORM_DIR_INVERSE;
const bool noInQualifier = shaderCreator->getLanguage() == LANGUAGE_OSL_1 ||
shaderCreator->getLanguage() == GPU_LANGUAGE_MSL_2_0;
const std::string in = noInQualifier ? "" : "in ";
// The inverse eval omits identity_x (returns the input when there is no curve), matching the CPU evalCurveRev signature.
if (inverse)
{
st.newLine() << st.floatKeyword() << " " << props.m_eval << "(int curveIdx, float x, float identity_x)";
st.newLine() << st.floatKeyword() << " " << props.m_eval << "(" << in << "int curveIdx, " << in << "float x)";
}
else
{
st.newLine() << st.floatKeyword() << " " << props.m_eval << "(in int curveIdx, in float x, in float identity_x)";
st.newLine() << st.floatKeyword() << " " << props.m_eval << "(" << in << "int curveIdx, " << in << "float x, " << in << "float identity_x)";
}
st.newLine() << "{";
st.indent();
if (gcData->getDirection() == TRANSFORM_DIR_INVERSE)
if (inverse)
{
GradingBSplineCurveImpl::AddShaderEvalRev(st, props.m_knotsOffsets, props.m_coefsOffsets,
props.m_knots, props.m_coefs);
Expand Down Expand Up @@ -331,13 +336,13 @@ void AddGCInverseShader(GpuShaderCreatorRcPtr & shaderCreator,

const std::string pix(shaderCreator->getPixelName());

// Call the curve evaluation method for each curve.
st.newLine() << pix << ".rgb.r = " << props.m_eval << "(3, " << pix << ".rgb.r, " << pix << ".rgb.r);"; // MASTER
st.newLine() << pix << ".rgb.g = " << props.m_eval << "(3, " << pix << ".rgb.g, " << pix << ".rgb.g);"; // MASTER
st.newLine() << pix << ".rgb.b = " << props.m_eval << "(3, " << pix << ".rgb.b, " << pix << ".rgb.b);"; // MASTER
st.newLine() << pix << ".rgb.r = " << props.m_eval << "(0, " << pix << ".rgb.r, " << pix << ".rgb.r);"; // RED
st.newLine() << pix << ".rgb.g = " << props.m_eval << "(1, " << pix << ".rgb.g, " << pix << ".rgb.g);"; // GREEN
st.newLine() << pix << ".rgb.b = " << props.m_eval << "(2, " << pix << ".rgb.b, " << pix << ".rgb.b);"; // BLUE
// Call the curve evaluation method for each curve (inverse eval takes no identity_x).
st.newLine() << pix << ".rgb.r = " << props.m_eval << "(3, " << pix << ".rgb.r);"; // MASTER
st.newLine() << pix << ".rgb.g = " << props.m_eval << "(3, " << pix << ".rgb.g);"; // MASTER
st.newLine() << pix << ".rgb.b = " << props.m_eval << "(3, " << pix << ".rgb.b);"; // MASTER
st.newLine() << pix << ".rgb.r = " << props.m_eval << "(0, " << pix << ".rgb.r);"; // RED
st.newLine() << pix << ".rgb.g = " << props.m_eval << "(1, " << pix << ".rgb.g);"; // GREEN
st.newLine() << pix << ".rgb.b = " << props.m_eval << "(2, " << pix << ".rgb.b);"; // BLUE

if (doLinToLog)
{
Expand Down
24 changes: 21 additions & 3 deletions src/libutils/oglapphelpers/dxapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,17 @@ void DxApp::setShader(GpuShaderDescRcPtr& shaderDesc)
sourceBuffer.Size = sourceBlob->GetBufferSize();
sourceBuffer.Encoding = DXC_CP_UTF8;

// Compile pixel shader (ps_6_0).
LPCWSTR psArgs[] = { L"-T", L"ps_6_0", L"-E", L"PSMain" };
// Compile pixel shader (ps_6_0). Opt-in: surface useful DXC warnings on the generated HLSL when verbose.
std::vector<LPCWSTR> psArgs = { L"-T", L"ps_6_0", L"-E", L"PSMain" };
if (isShaderVerbose())
{
psArgs.push_back(L"-Wall");
psArgs.push_back(L"-Wextra");
psArgs.push_back(L"-Wconversion");
}
ComPtr<IDxcResult> psResult;
ThrowIfFailed(m_dxcCompiler->Compile(&sourceBuffer, psArgs, _countof(psArgs),
ThrowIfFailed(m_dxcCompiler->Compile(&sourceBuffer, psArgs.data(),
static_cast<UINT32>(psArgs.size()),
nullptr, IID_PPV_ARGS(&psResult)));
HRESULT psHr;
psResult->GetStatus(&psHr);
Expand All @@ -586,6 +593,17 @@ void DxApp::setShader(GpuShaderDescRcPtr& shaderDesc)
std::cerr << oss.str() << std::endl;
throw Exception(oss.str().c_str());
}
// Opt-in: surface DXC warnings (carried on the ERRORS output even on success) when verbose.
if (isShaderVerbose())
{
ComPtr<IDxcBlobUtf8> psWarnings;
psResult->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&psWarnings), nullptr);
if (psWarnings && psWarnings->GetStringLength())
{
std::cerr << "[DXC-WARN] pixel shader '" << shaderDesc->getFunctionName()
<< "':\n" << psWarnings->GetStringPointer() << std::endl;
}
}
ComPtr<IDxcBlob> pixelShaderBlob;
ThrowIfFailed(psResult->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&pixelShaderBlob), nullptr));

Expand Down