From 6c8ae19be66cee247980a48e736a4e05d14de179 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Tue, 2 Dec 2025 16:39:36 -0800 Subject: Immediate-mode renderer, triangle demo, shader compilation in cmake, Agility SDK --- dxg/shaders/CMakeLists.txt | 98 ++++++++++++++++++++++++++++++++++++++++++++++ dxg/shaders/imm.hlsl | 23 +++++++++++ 2 files changed, 121 insertions(+) create mode 100644 dxg/shaders/CMakeLists.txt create mode 100644 dxg/shaders/imm.hlsl (limited to 'dxg/shaders') diff --git a/dxg/shaders/CMakeLists.txt b/dxg/shaders/CMakeLists.txt new file mode 100644 index 0000000..c6ec687 --- /dev/null +++ b/dxg/shaders/CMakeLists.txt @@ -0,0 +1,98 @@ +set(SHADER_MODEL "6_5") +set(DXC ${PROJECT_SOURCE_DIR}/../contrib/dxc_2025_07_14/bin/x64/dxc.exe) +set(SHADERS_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +set(BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +# Compile HLSL to binary DXIL. +# +# This defines a custom command so that the shader is compiled at cmake build +# instead of configure. +# +# hlsl_file: "foo.hlsl"; just the file name, not the path. +# shader_type: "vs", "ps", "cs", etc. +# entry_point: "main", etc. +function(compile_shader hlsl_file shader_type entry_point dxil_file) + #string(REPLACE ".hlsl" ".dxil" dxil_file ${hlsl_file}) + set(hlsl_path "${SHADERS_PATH}/${hlsl_file}") + set(dxil_path "${BUILD_DIR}/${dxil_file}") + set(target_profile "${shader_type}_${SHADER_MODEL}") + message("COMPILING ${dxil_path}") + message("DXC = ${DXC}") + add_custom_command( + OUTPUT ${dxil_path} + COMMAND ${DXC} -T ${target_profile} -E ${entry_point} ${hlsl_path} -Fo ${dxil_path} + WORKING_DIRECTORY ${BUILD_DIR} + DEPENDS ${hlsl_path} + COMMENT "Generating ${dxil_path}") +endfunction() + +# Inline a binary file into C code. +# This is a workaround for the lack of C23 #embed in MSVC. +# +# identifier: Identifier to use for the global array that will contain the file, +# the generated file names, and the cmake target. +# file_path: Path to the binary file to embed. +# +# Reference: https://github.com/andoalon/embed-binaries +function(generate_c file_path identifier out_header_path out_source_path) + file(READ "${file_path}" file_contents HEX) + string(LENGTH "${file_contents}" file_contents_length) + math(EXPR file_bytes "${file_contents_length} / 2") + + set(bytes_per_line 32) + string(REPEAT "[0-9a-f]" ${bytes_per_line} column_pattern) + string(REGEX REPLACE "(${column_pattern})" "\\1\n" code "${file_contents}") + string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," code "${code}") + + set(declaration "const uint8_t ${identifier}[${file_bytes}]") + + string(APPEND header "#pragma once\n\n#include \n\nextern ${declaration}\;\n") + string(APPEND implementation "#include \"${identifier}.h\"\n\n${declaration} = {\n${code}}\;\n") + + file(WRITE "${BUILD_DIR}/${identifier}.h" ${header}) + file(WRITE "${BUILD_DIR}/${identifier}.c" ${implementation}) +endfunction() + +# Create a target that embeds the given DXIL file in a C header/source. +# Like compile_shader, this just adds the target so that the embedding is done +# at cmake build and not configure. +function(create_c_target dxil_file identifier) + set(dxil_path "${BUILD_DIR}/${dxil_file}") + string(REPLACE ".dxil" ".h" header_path ${dxil_path}) + string(REPLACE ".dxil" ".c" source_path ${dxil_path}) + add_custom_command( + OUTPUT "${header_path}" "${source_path}" + COMMAND ${CMAKE_COMMAND} -D dxil_path=${dxil_path} -D identifier=${identifier} -D out_header_path=${header_path} -D out_source_path=${source_path} -P ${CMAKE_CURRENT_LIST_FILE} + WORKING_DIRECTORY ${BUILD_DIR} + DEPENDS ${dxil_path} + COMMENT "Generating ${source_path}" + ) +endfunction() + +# Running in script mode. +# https://stackoverflow.com/questions/51427538/cmake-test-if-i-am-in-scripting-mode +# +# When running in script mode, we embed the binary DXIL into a generated C file. +if(CMAKE_SCRIPT_MODE_FILE AND NOT CMAKE_PARENT_LIST_FILE) + foreach(variable "dxil_path" "identifier" "out_header_path" "out_source_path") + if (NOT DEFINED ${variable}) + message(FATAL_ERROR "'${variable}' is not defined") + endif() + endforeach() + generate_c("${dxil_path}" ${identifier} "${out_header_path}" "${out_source_path}") +else() + compile_shader("imm.hlsl" "vs" "vs" "imm_vs.dxil") + compile_shader("imm.hlsl" "ps" "ps" "imm_ps.dxil") + + create_c_target("imm_vs.dxil" "imm_vs") + create_c_target("imm_ps.dxil" "imm_ps") + + add_library(shaders + "${BUILD_DIR}/imm_ps.c" + "${BUILD_DIR}/imm_ps.h" + "${BUILD_DIR}/imm_vs.c" + "${BUILD_DIR}/imm_vs.h") + + target_include_directories(shaders PUBLIC + ${BUILD_DIR}) +endif() diff --git a/dxg/shaders/imm.hlsl b/dxg/shaders/imm.hlsl new file mode 100644 index 0000000..da6b1f6 --- /dev/null +++ b/dxg/shaders/imm.hlsl @@ -0,0 +1,23 @@ +struct VertexIn { + float3 position : POSITION; +}; + +struct VertexOut { + float4 position : SV_POSITION; +}; + +struct PixelOut { + float4 color : SV_TARGET; +}; + +VertexOut vs(VertexIn vin) { + VertexOut vout; + vout.position = float4(vin.position, 1.0f); + return vout; +} + +PixelOut ps(VertexOut vout) { + PixelOut pixel; + pixel.color = float4(0.9f, 0.2f, 0.9f, 1.0f); + return pixel; +} -- cgit v1.2.3