diff --git a/.gitignore b/.gitignore index 7a2059c..242c19a 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ __pycache__/ # Compiled shaders *.spv +*.dxil diff --git a/SConstruct b/SConstruct index ac7f8f1..79014ae 100644 --- a/SConstruct +++ b/SConstruct @@ -1,6 +1,6 @@ config = { 'PROJECT_NAME': 'sdl_gpu_test', - 'TOOLS': ['glslang'] + 'TOOLS': ['glslang', 'dxc'] } env = SConscript('external/scons-plus-plus/SConscript', exports = ['config']) env.Append(CPPPATH = [Dir('private'), Dir('public')]) diff --git a/private/sdl_gpu_test/1_green_triangle_dxil/app.cpp b/private/sdl_gpu_test/1_green_triangle_dxil/app.cpp new file mode 100644 index 0000000..626915b --- /dev/null +++ b/private/sdl_gpu_test/1_green_triangle_dxil/app.cpp @@ -0,0 +1,64 @@ + +#include "./app.hpp" + +namespace sdl_gpu_test +{ +void GreenTriangleDXILApp::init(const AppInitArgs& args) +{ + mOptions.shaderFormats = {.dxil = true}; + Application::init(args); + + // create vertex shader + mijin::TypelessBuffer vertexSpv = getFileContentsBinary("shaders/hlsl/triangle.vs.dxil"); + sdlpp::GPUShader vertexShader; + vertexShader.create(mDevice, { + .code = {static_cast(vertexSpv.data()), vertexSpv.byteSize()}, + .format = sdlpp::GPUShaderFormat::DXIL, + .stage = sdlpp::GPUShaderStage::VERTEX + }); + + // create fragment shader + mijin::TypelessBuffer fragmentSpv = getFileContentsBinary("shaders/hlsl/green.ps.dxil"); + sdlpp::GPUShader fragmentShader; + fragmentShader.create(mDevice, { + .code = {static_cast(fragmentSpv.data()), fragmentSpv.byteSize()}, + .format = sdlpp::GPUShaderFormat::DXIL, + .stage = sdlpp::GPUShaderStage::FRAGMENT + }); + + // create graphics pipeline + std::array colorTargetsDescs = { + sdlpp::GPUColorTargetDescription{ + .format = mDevice.getSwapchainTextureFormat(mWindow) + } + }; + mPipeline.create(mDevice, { + .vertexShader = vertexShader, + .fragmentShader = fragmentShader, + .targetInfo = { + .colorTargetDescriptions = colorTargetsDescs + } + }); +} + +void GreenTriangleDXILApp::update(const AppUpdateArgs& args) +{ + Application::update(args); + + sdlpp::GPUCommandBuffer cmdBuffer = mDevice.acquireCommandBuffer(); + Uint32 swapchainWidth = 0, swapchainHeight = 0; + sdlpp::GPUTexture swapchainTexture = cmdBuffer.acquireSwapchainTexture(mWindow, swapchainWidth, swapchainHeight); + std::array colorTargets = {sdlpp::GPUColorTargetInfo{ + .texture = swapchainTexture, + .clearColor = {.r = 1.f, .g = 0.f, .b = 0.f, .a = 1.f}, + .loadOp = sdlpp::GPULoadOp::CLEAR, + }}; + sdlpp::GPURenderPass renderPass = cmdBuffer.beginRenderPass({ + .colorTargetInfos = colorTargets + }); + renderPass.bindGraphicsPipeline(mPipeline); + renderPass.drawPrimitives({.numVertices = 3}); + renderPass.end(); + cmdBuffer.submit(); +} +} diff --git a/private/sdl_gpu_test/1_green_triangle_dxil/app.hpp b/private/sdl_gpu_test/1_green_triangle_dxil/app.hpp new file mode 100644 index 0000000..77cae81 --- /dev/null +++ b/private/sdl_gpu_test/1_green_triangle_dxil/app.hpp @@ -0,0 +1,21 @@ + +#pragma once + +#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_1_GREEN_TRIANGLE_DXIL_APP_HPP_INCLUDED) +#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_1_GREEN_TRIANGLE_DXIL_APP_HPP_INCLUDED 1 + +#include "../application.hpp" + +namespace sdl_gpu_test +{ +class GreenTriangleDXILApp : public Application +{ +private: + sdlpp::GPUGraphicsPipeline mPipeline; +public: + void init(const AppInitArgs& args) override; + void update(const AppUpdateArgs& args) override; +}; +} // namespace sdl_gpu_test + +#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_1_GREEN_TRIANGLE_DXIL_APP_HPP_INCLUDED) diff --git a/private/sdl_gpu_test/SModule b/private/sdl_gpu_test/SModule index ccab8dc..154aa3b 100644 --- a/private/sdl_gpu_test/SModule +++ b/private/sdl_gpu_test/SModule @@ -20,7 +20,9 @@ src_files = Split(""" util/texture_atlas.cpp 0_clear_swapchain/app.cpp + 0_clear_swapchain_dxil/app.cpp 1_green_triangle/app.cpp + 1_green_triangle_dxil/app.cpp 2_triangle_with_texcoords/app.cpp 3_textured_quad/app.cpp 4_textured_cube/app.cpp @@ -30,9 +32,12 @@ src_files = Split(""" 8_post_process/app.cpp """) -shader_files = env.Glob("#assets/shaders/glsl/*.frag") \ - + env.Glob("#assets/shaders/glsl/*.vert") \ - + env.Glob("#assets/shaders/glsl/*.comp") +glsl_files = env.Glob("#assets/shaders/glsl/*.frag") \ + + env.Glob("#assets/shaders/glsl/*.vert") \ + + env.Glob("#assets/shaders/glsl/*.comp") + +hlsl_files = env.Glob('#assets/shaders/hlsl/*.ps') \ + + env.Glob('#assets/shaders/hlsl/*.vs') env.Append(CPPDEFINES = ['GLM_FORCE_DEPTH_ZERO_TO_ONE', 'GLM_FORCE_RADIANS', 'GLM_ENABLE_EXPERIMENTAL']) prog_app = env.UnityProgram( @@ -55,10 +60,15 @@ prog_app = env.UnityProgram( ) env.Default(prog_app) -for shader_file in shader_files: - spv = env.SpirV(source = shader_file, target=f'{shader_file}.spv') +for glsl_file in glsl_files: + spv = env.SpirV(source=glsl_file, target=f'{glsl_file}.spv') env.Default(spv) +if 'DXC' in env['BUILDERS']: + for hlsl_file in hlsl_files: + dxc = env.DXC(source=hlsl_file, target=f'{hlsl_file}.dxil') + env.Default(dxc) + pack = env.PackTextures( target = '#assets/bitmaps/ui.png', source = ['#assets/bitmaps/ui_elements.txt'] diff --git a/private/sdl_gpu_test/main.cpp b/private/sdl_gpu_test/main.cpp index 78ef930..dd19b7c 100644 --- a/private/sdl_gpu_test/main.cpp +++ b/private/sdl_gpu_test/main.cpp @@ -3,7 +3,9 @@ #include #include "./0_clear_swapchain/app.hpp" +#include "./0_clear_swapchain_dxil/app.hpp" #include "./1_green_triangle/app.hpp" +#include "./1_green_triangle_dxil/app.hpp" #include "./2_triangle_with_texcoords/app.hpp" #include "./3_textured_quad/app.hpp" #include "./4_textured_cube/app.hpp" @@ -36,7 +38,9 @@ AppListEntry makeAppHelper(std::string name) noexcept const std::array APPS = { makeAppHelper("clear_swapchain"), + makeAppHelper("clear_swapchain_dxil"), makeAppHelper("green_triangle"), + makeAppHelper("green_triangle_dxil"), makeAppHelper("triangle_with_texcoords"), makeAppHelper("textured_quad"), makeAppHelper("textured_cube"), diff --git a/site_scons/site_tools/dxc.py b/site_scons/site_tools/dxc.py new file mode 100644 index 0000000..7d3c663 --- /dev/null +++ b/site_scons/site_tools/dxc.py @@ -0,0 +1,29 @@ + +import shutil +from SCons.Script import * + +def exists(env: Environment) -> bool: + return shutil.which('dxc.exe') is not None + +def generate(env : Environment): + if not exists(env): + return + def _build(target, source, env): + if len(target) != 1: + env.Error('Invalid number of targets for DXC builder, must be 1.') + if len(source) != 1: + env.Error('Invalid number of sources for DXC builder, must be 1.') + ext = source[0].name.split('.')[-1] + profile = { + 'vs': 'vs_6_0', + 'ps': 'ps_6_0' + }.get(ext.lower()) + if not profile: + env.Error(f'Could not detect DXC shader profile from extension: {ext}') + env.Execute(f'"$DXC" -O0 -Zi -E main -T {profile} -Fo "{target[0]}" -Fd "{target[0]}.pdb" "{source[0]}') + dxc_builder = Builder( + action=_build + ) + env.AddMethod(_build, 'DXC') + env['DXC'] = shutil.which('dxc.exe') + env.Append(BUILDERS={'DXC': dxc_builder})