Skip to content

Commit cf20a2a

Browse files
committed
Add DirectX 12 GPU backend for automated unit testing on Windows
Introduce a DirectX 12 / HLSL rendering backend alongside the existing OpenGL / GLSL and Metal / MSL backends, enabling the GPU unit test suite to run natively on Windows without requiring an OpenGL context. Key changes: GraphicalApp abstract interface (graphicalapp.h/cpp) Backend-agnostic base class extracted from OglApp. OglApp and MetalApp now inherit from it. DxApp (dxapp.h/cpp) -- DirectX 12 backend Off-screen RGBA32F render target, full-screen triangle via SV_VertexID, staging readback, SM 6.0 DXC shader compilation. HLSLBuilder (hlsl.h/cpp) -- HLSL shader generation Translates GpuShaderDesc into HLSL pixel shaders with 1D and 3D LUT texture uploads in RGBA32F format. CMake integration OCIO_DIRECTX_ENABLED option, FetchContent for DirectX-Headers, auto-copy of DXC runtime DLLs to the test output directory. Test tolerance adjustments Minor epsilon increases for 4 tests due to DX12/SM6.0 FMA and pow() precision differences. All 263 GPU tests pass on the DirectX 12 backend. Build and run: # Configure (OCIO_DIRECTX_ENABLED defaults to ON on Windows) cmake -S . -B build -DCMAKE_BUILD_TYPE=Release # Build the GPU test binary cmake --build build --target test_gpu_exec --config Release # Run GPU tests with the DX12 backend ctest --test-dir build -C Release -R test_dx Signed-off-by: Eric Renaud-Houde <eric.renaud.houde@gmail.com>
1 parent d9eb50c commit cf20a2a

File tree

21 files changed

+2207
-185
lines changed

21 files changed

+2207
-185
lines changed

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,14 @@ message(STATUS "")
287287
message(STATUS "Checking for GPU configuration...")
288288
include(CheckSupportGL)
289289

290+
# DirectX 12 is only available on Windows.
291+
if(WIN32)
292+
option(OCIO_DIRECTX_ENABLED "Enable DirectX 12 GPU rendering support" ON)
293+
else()
294+
set(OCIO_DIRECTX_ENABLED OFF CACHE BOOL "Enable DirectX 12 GPU rendering support" FORCE)
295+
endif()
296+
mark_as_advanced(OCIO_DIRECTX_ENABLED)
297+
290298

291299
###############################################################################
292300
# Check for ARM neon here because we need to know if ARM NEON is supported
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
# Copyright Contributors to the OpenColorIO Project.
3+
#
4+
# Install DirectX-Headers (header-only, Windows only)
5+
# https://github.com/microsoft/DirectX-Headers
6+
#
7+
###############################################################################
8+
9+
include(FetchContent)
10+
11+
set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/ext/build/DirectX-Headers")
12+
set(DIRECTX_HEADERS_BUILD_TEST OFF CACHE BOOL "" FORCE)
13+
14+
FetchContent_Declare(DirectX-Headers
15+
GIT_REPOSITORY https://github.com/microsoft/DirectX-Headers.git
16+
GIT_TAG v1.619.1
17+
)
18+
19+
FetchContent_MakeAvailable(DirectX-Headers)

src/apps/ociochecklut/main.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,18 @@ class ProcessorWrapper
5252
m_gpu = gpu;
5353
if (!m_oglApp)
5454
{
55-
m_oglApp = OCIO::OglApp::CreateOglApp("ociochecklut", 256, 20);
55+
m_oglApp = OCIO::GraphicalApp::CreateApp("ociochecklut", 256, 20);
5656

5757
if (m_verbose)
5858
{
59-
m_oglApp->printGLInfo();
59+
m_oglApp->printGraphicsInfo();
6060
}
6161
}
6262

63-
m_oglApp->setPrintShader(m_verbose);
63+
m_oglApp->setShaderVerbose(m_verbose);
6464
float image[4]{ 0.f, 0.f, 0.f, 0.f };
65-
m_oglApp->initImage(1, 1, OCIO::OglApp::COMPONENTS_RGBA, image);
66-
m_oglApp->createGLBuffers();
65+
m_oglApp->initImage(1, 1, OCIO::GraphicalApp::COMPONENTS_RGBA, image);
66+
m_oglApp->createBuffers();
6767
OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();
6868
shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
6969
m_gpu->extractGpuShaderInfo(shaderDesc);
@@ -98,7 +98,7 @@ class ProcessorWrapper
9898
m_oglApp->redisplay();
9999
m_oglApp->readImage(pixel.data());
100100
}
101-
OCIO::OglAppRcPtr m_oglApp;
101+
OCIO::GraphicalAppRcPtr m_oglApp;
102102
#else
103103
void applyGPU(std::vector<float> &)
104104
{

src/apps/ocioconvert/main.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,18 @@ int main(int argc, const char **argv)
361361

362362
#ifdef OCIO_GPU_ENABLED
363363
// Initialize GPU.
364-
OCIO::OglAppRcPtr oglApp;
364+
OCIO::GraphicalAppRcPtr oglApp;
365365

366366
if (usegpu || usegpuLegacy)
367367
{
368-
OCIO::OglApp::Components comp = OCIO::OglApp::COMPONENTS_RGBA;
368+
OCIO::GraphicalApp::Components comp = OCIO::GraphicalApp::COMPONENTS_RGBA;
369369
if (imgInput.getNumChannels() == 4)
370370
{
371-
comp = OCIO::OglApp::COMPONENTS_RGBA;
371+
comp = OCIO::GraphicalApp::COMPONENTS_RGBA;
372372
}
373373
else if (imgInput.getNumChannels() == 3)
374374
{
375-
comp = OCIO::OglApp::COMPONENTS_RGB;
375+
comp = OCIO::GraphicalApp::COMPONENTS_RGB;
376376
}
377377
else
378378
{
@@ -383,7 +383,7 @@ int main(int argc, const char **argv)
383383

384384
try
385385
{
386-
oglApp = OCIO::OglApp::CreateOglApp("ocioconvert", 256, 20);
386+
oglApp = OCIO::GraphicalApp::CreateApp("ocioconvert", 256, 20);
387387
}
388388
catch (const OCIO::Exception & e)
389389
{
@@ -393,14 +393,14 @@ int main(int argc, const char **argv)
393393

394394
if (verbose)
395395
{
396-
oglApp->printGLInfo();
396+
oglApp->printGraphicsInfo();
397397
}
398398

399-
oglApp->setPrintShader(outputgpuInfo);
399+
oglApp->setShaderVerbose(outputgpuInfo);
400400

401401
oglApp->initImage(imgInput.getWidth(), imgInput.getHeight(), comp, (float *)imgInput.getData());
402402

403-
oglApp->createGLBuffers();
403+
oglApp->createBuffers();
404404
}
405405
#endif // OCIO_GPU_ENABLED
406406

src/apps/ociodisplay/main.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ float g_display_gamma{1.0f};
6464
int g_channelHot[4]{1, 1, 1, 1}; // show rgb
6565
int g_viewsMenuID;
6666

67-
OCIO::OglAppRcPtr g_oglApp;
67+
OCIO::GraphicalAppRcPtr g_oglApp;
6868

6969
void UpdateOCIOGLState();
7070

@@ -115,14 +115,14 @@ static void InitImageTexture(const char * filename)
115115
}
116116
}
117117

118-
OCIO::OglApp::Components comp = OCIO::OglApp::COMPONENTS_RGBA;
118+
OCIO::GraphicalApp::Components comp = OCIO::GraphicalApp::COMPONENTS_RGBA;
119119
if (img.getNumChannels() == 4)
120120
{
121-
comp = OCIO::OglApp::COMPONENTS_RGBA;
121+
comp = OCIO::GraphicalApp::COMPONENTS_RGBA;
122122
}
123123
else if (img.getNumChannels() == 3)
124124
{
125-
comp = OCIO::OglApp::COMPONENTS_RGB;
125+
comp = OCIO::GraphicalApp::COMPONENTS_RGB;
126126
}
127127
else
128128
{
@@ -658,7 +658,7 @@ int main(int argc, char **argv)
658658
else
659659
#endif
660660
{
661-
g_oglApp = std::make_shared<OCIO::ScreenApp>("ociodisplay", 512, 512);
661+
g_oglApp = std::make_shared<OCIO::ScreenOglApp>("ociodisplay", 512, 512);
662662
}
663663
}
664664
catch (const OCIO::Exception &e)
@@ -669,11 +669,11 @@ int main(int argc, char **argv)
669669

670670
if (g_verbose)
671671
{
672-
g_oglApp->printGLInfo();
672+
g_oglApp->printGraphicsInfo();
673673
}
674674

675675
g_oglApp->setYMirror();
676-
g_oglApp->setPrintShader(g_gpuinfo);
676+
g_oglApp->setShaderVerbose(g_gpuinfo);
677677

678678
glutReshapeFunc(Reshape);
679679
glutKeyboardFunc(Key);

src/libutils/oglapphelpers/CMakeLists.txt

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,41 @@
11
# SPDX-License-Identifier: BSD-3-Clause
22
# Copyright Contributors to the OpenColorIO Project.
33

4-
if(NOT OCIO_GL_ENABLED)
5-
message(WARNING "GL component missing. Skipping oglapphelpers.")
4+
if(NOT OCIO_GL_ENABLED AND NOT (WIN32 AND OCIO_DIRECTX_ENABLED))
5+
message(WARNING "GL component missing and DirectX disabled. Skipping oglapphelpers.")
66
return()
77
endif()
88

99
set(SOURCES
10-
glsl.cpp
11-
oglapp.cpp
10+
graphicalapp.cpp
1211
)
1312
set(INCLUDES
14-
glsl.h
15-
oglapp.h
13+
graphicalapp.h
1614
)
1715

16+
if(OCIO_GL_ENABLED)
17+
list(APPEND SOURCES
18+
glsl.cpp
19+
oglapp.cpp
20+
)
21+
list(APPEND INCLUDES
22+
glsl.h
23+
oglapp.h
24+
)
25+
endif()
26+
27+
if(WIN32 AND OCIO_DIRECTX_ENABLED)
28+
list(APPEND SOURCES
29+
dxapp.cpp
30+
hlsl.cpp
31+
)
32+
list(APPEND INCLUDES
33+
dxapp.h
34+
dxutils.h
35+
hlsl.h
36+
)
37+
endif()
38+
1839
if(APPLE)
1940

2041
list(APPEND SOURCES
@@ -31,7 +52,7 @@ if(APPLE)
3152

3253
endif()
3354

34-
add_library(oglapphelpers STATIC ${SOURCES})
55+
add_library(oglapphelpers STATIC ${INCLUDES} ${SOURCES})
3556
set_target_properties(oglapphelpers PROPERTIES POSITION_INDEPENDENT_CODE ON)
3657
set_target_properties(oglapphelpers PROPERTIES OUTPUT_NAME OpenColorIOoglapphelpers)
3758

@@ -56,47 +77,55 @@ set_target_properties(oglapphelpers PROPERTIES
5677
target_include_directories(oglapphelpers
5778
PUBLIC
5879
${CMAKE_CURRENT_SOURCE_DIR}
59-
PRIVATE
60-
${OPENGL_INCLUDE_DIR}
61-
${GLEW_INCLUDE_DIRS}
62-
${GLUT_INCLUDE_DIR}
6380
)
6481

82+
if(OCIO_GL_ENABLED)
83+
target_include_directories(oglapphelpers
84+
PRIVATE
85+
${OPENGL_INCLUDE_DIR}
86+
${GLEW_INCLUDE_DIRS}
87+
${GLUT_INCLUDE_DIR}
88+
)
89+
endif()
6590

66-
if(${OCIO_USE_GLVND})
67-
if(${OCIO_EGL_HEADLESS})
68-
target_include_directories(oglapphelpers
69-
PRIVATE
70-
${OPENGL_EGL_INCLUDE_DIRS}
71-
)
72-
target_link_libraries(oglapphelpers
73-
PRIVATE
74-
OpenColorIO
75-
OpenGL::OpenGL
76-
OpenGL::GLU
77-
${GLEW_LIBRARIES}
78-
${GLUT_LIBRARIES}
79-
OpenGL::EGL
91+
target_link_libraries(oglapphelpers
92+
PRIVATE
93+
OpenColorIO
94+
)
95+
96+
if(OCIO_GL_ENABLED)
97+
if(${OCIO_USE_GLVND})
98+
if(${OCIO_EGL_HEADLESS})
99+
target_include_directories(oglapphelpers
100+
PRIVATE
101+
${OPENGL_EGL_INCLUDE_DIRS}
80102
)
103+
target_link_libraries(oglapphelpers
104+
PRIVATE
105+
OpenGL::OpenGL
106+
OpenGL::GLU
107+
${GLEW_LIBRARIES}
108+
${GLUT_LIBRARIES}
109+
OpenGL::EGL
110+
)
111+
else()
112+
target_link_libraries(oglapphelpers
113+
PRIVATE
114+
OpenGL::OpenGL
115+
OpenGL::GLU
116+
${GLEW_LIBRARIES}
117+
${GLUT_LIBRARIES}
118+
)
119+
endif()
81120
else()
121+
# if OCIO_USE_GLVND is OFF, OCIO_EGL_HEADLESS is also OFF
82122
target_link_libraries(oglapphelpers
83123
PRIVATE
84-
OpenColorIO
85-
OpenGL::OpenGL
86-
OpenGL::GLU
124+
${OPENGL_LIBRARIES}
87125
${GLEW_LIBRARIES}
88126
${GLUT_LIBRARIES}
89-
)
90-
endif()
91-
else()
92-
# if OCIO_USE_GLVND is OFF, OCIO_EGL_HEADLESS is also OFF
93-
target_link_libraries(oglapphelpers
94-
PRIVATE
95-
OpenColorIO
96-
${OPENGL_LIBRARIES}
97-
${GLEW_LIBRARIES}
98-
${GLUT_LIBRARIES}
99-
)
127+
)
128+
endif()
100129
endif()
101130

102131
if(APPLE)
@@ -111,6 +140,30 @@ if(APPLE)
111140
)
112141
endif()
113142

143+
if(OCIO_GL_ENABLED)
144+
target_compile_definitions(oglapphelpers
145+
PUBLIC
146+
OCIO_GL_ENABLED
147+
)
148+
endif()
149+
150+
if(WIN32 AND OCIO_DIRECTX_ENABLED)
151+
include(InstallDirectXHeaders)
152+
target_compile_definitions(oglapphelpers
153+
PUBLIC
154+
OCIO_DIRECTX_ENABLED
155+
)
156+
target_link_libraries(oglapphelpers
157+
PUBLIC
158+
Microsoft::DirectX-Headers
159+
PRIVATE
160+
d3d12
161+
dxgi
162+
dxcompiler
163+
dxguid
164+
)
165+
endif()
166+
114167
if(${OCIO_EGL_HEADLESS})
115168
target_include_directories(oglapphelpers
116169
PRIVATE

0 commit comments

Comments
 (0)