├── .gitmodules ├── .gitignore ├── Content ├── Images │ ├── cube0.bmp │ ├── cube1.bmp │ ├── cube2.bmp │ ├── cube3.bmp │ ├── cube4.bmp │ ├── cube5.bmp │ ├── armadillo.png │ ├── astc │ │ ├── 4x4.astc │ │ ├── 5x4.astc │ │ ├── 5x5.astc │ │ ├── 6x5.astc │ │ ├── 6x6.astc │ │ ├── 8x5.astc │ │ ├── 8x6.astc │ │ ├── 8x8.astc │ │ ├── 10x10.astc │ │ ├── 10x5.astc │ │ ├── 10x6.astc │ │ ├── 10x8.astc │ │ ├── 12x10.astc │ │ └── 12x12.astc │ ├── bcn │ │ ├── BC1.dds │ │ ├── BC2.dds │ │ ├── BC3.dds │ │ ├── BC4.dds │ │ ├── BC5.dds │ │ ├── BC7.dds │ │ ├── BC6H_S.dds │ │ ├── BC6H_U.dds │ │ ├── BC1_SRGB.dds │ │ ├── BC2_SRGB.dds │ │ ├── BC3_SRGB.dds │ │ └── BC7_SRGB.dds │ ├── cube0mip1.bmp │ ├── cube1mip1.bmp │ ├── cube2mip1.bmp │ ├── cube3mip1.bmp │ ├── latency.bmp │ ├── memorial.hdr │ ├── ravioli.bmp │ ├── ravioli_atlas.bmp │ └── ravioli_inverted.bmp └── Shaders │ ├── Source │ ├── SolidColor.frag.hlsl │ ├── TexturedQuad.frag.hlsl │ ├── Skybox.frag.hlsl │ ├── FillTexture.comp.hlsl │ ├── TexturedQuadArray.frag.hlsl │ ├── TexturedQuadColor.frag.hlsl │ ├── TexturedQuadWithMultiplyColor.frag.hlsl │ ├── PositionColor.vert.hlsl │ ├── Fullscreen.vert.hlsl │ ├── TexturedQuad.vert.hlsl │ ├── PositionColorTransform.vert.hlsl │ ├── ToneMapReinhard.comp.hlsl │ ├── Skybox.vert.hlsl │ ├── TexturedQuadWithMatrix.vert.hlsl │ ├── LinearToSRGB.comp.hlsl │ ├── GradientTexture.comp.hlsl │ ├── PositionColorInstanced.vert.hlsl │ ├── SolidColorDepth.frag.hlsl │ ├── TexturedQuadColorWithMatrix.vert.hlsl │ ├── TexturedQuad.comp.hlsl │ ├── CustomSampling.frag.hlsl │ ├── RawTriangle.vert.hlsl │ ├── ToneMapACES.comp.hlsl │ ├── ToneMapExtendedReinhardLuminance.comp.hlsl │ ├── compile.sh │ ├── ToneMapHable.comp.hlsl │ ├── LinearToST2084.comp.hlsl │ ├── DepthOutline.frag.hlsl │ ├── PullSpriteBatch.vert.hlsl │ └── SpriteBatch.comp.hlsl │ └── Compiled │ ├── DXIL │ ├── Skybox.frag.dxil │ ├── Skybox.vert.dxil │ ├── Fullscreen.vert.dxil │ ├── SolidColor.frag.dxil │ ├── DepthOutline.frag.dxil │ ├── FillTexture.comp.dxil │ ├── LinearToSRGB.comp.dxil │ ├── PositionColor.vert.dxil │ ├── RawTriangle.vert.dxil │ ├── SpriteBatch.comp.dxil │ ├── TexturedQuad.comp.dxil │ ├── TexturedQuad.frag.dxil │ ├── TexturedQuad.vert.dxil │ ├── ToneMapACES.comp.dxil │ ├── ToneMapHable.comp.dxil │ ├── CustomSampling.frag.dxil │ ├── GradientTexture.comp.dxil │ ├── LinearToST2084.comp.dxil │ ├── PullSpriteBatch.vert.dxil │ ├── SolidColorDepth.frag.dxil │ ├── ToneMapReinhard.comp.dxil │ ├── TexturedQuadArray.frag.dxil │ ├── TexturedQuadColor.frag.dxil │ ├── PositionColorInstanced.vert.dxil │ ├── PositionColorTransform.vert.dxil │ ├── TexturedQuadWithMatrix.vert.dxil │ ├── TexturedQuadColorWithMatrix.vert.dxil │ ├── TexturedQuadWithMultiplyColor.frag.dxil │ └── ToneMapExtendedReinhardLuminance.comp.dxil │ ├── SPIRV │ ├── Skybox.frag.spv │ ├── Skybox.vert.spv │ ├── Fullscreen.vert.spv │ ├── SolidColor.frag.spv │ ├── DepthOutline.frag.spv │ ├── FillTexture.comp.spv │ ├── LinearToSRGB.comp.spv │ ├── PositionColor.vert.spv │ ├── RawTriangle.vert.spv │ ├── SpriteBatch.comp.spv │ ├── TexturedQuad.comp.spv │ ├── TexturedQuad.frag.spv │ ├── TexturedQuad.vert.spv │ ├── ToneMapACES.comp.spv │ ├── ToneMapHable.comp.spv │ ├── CustomSampling.frag.spv │ ├── GradientTexture.comp.spv │ ├── LinearToST2084.comp.spv │ ├── PullSpriteBatch.vert.spv │ ├── SolidColorDepth.frag.spv │ ├── ToneMapReinhard.comp.spv │ ├── TexturedQuadArray.frag.spv │ ├── TexturedQuadColor.frag.spv │ ├── PositionColorInstanced.vert.spv │ ├── PositionColorTransform.vert.spv │ ├── TexturedQuadWithMatrix.vert.spv │ ├── TexturedQuadColorWithMatrix.vert.spv │ ├── TexturedQuadWithMultiplyColor.frag.spv │ └── ToneMapExtendedReinhardLuminance.comp.spv │ └── MSL │ ├── FillTexture.comp.msl │ ├── SolidColor.frag.msl │ ├── LinearToSRGB.comp.msl │ ├── ToneMapReinhard.comp.msl │ ├── TexturedQuad.frag.msl │ ├── Skybox.frag.msl │ ├── Fullscreen.vert.msl │ ├── PositionColor.vert.msl │ ├── TexturedQuad.vert.msl │ ├── TexturedQuadColor.frag.msl │ ├── TexturedQuadArray.frag.msl │ ├── GradientTexture.comp.msl │ ├── ToneMapExtendedReinhardLuminance.comp.msl │ ├── Skybox.vert.msl │ ├── TexturedQuadWithMultiplyColor.frag.msl │ ├── PositionColorTransform.vert.msl │ ├── TexturedQuad.comp.msl │ ├── ToneMapHable.comp.msl │ ├── TexturedQuadWithMatrix.vert.msl │ ├── PositionColorInstanced.vert.msl │ ├── SolidColorDepth.frag.msl │ ├── TexturedQuadColorWithMatrix.vert.msl │ ├── LinearToST2084.comp.msl │ ├── RawTriangle.vert.msl │ ├── ToneMapACES.comp.msl │ ├── CustomSampling.frag.msl │ ├── DepthOutline.frag.msl │ ├── SpriteBatch.comp.msl │ └── PullSpriteBatch.vert.msl ├── README.md ├── LICENSE ├── Examples ├── ClearScreen.c ├── ClearScreenMultiWindow.c ├── ComputeUniforms.c ├── GenerateMipmaps.c ├── Common.h ├── WindowResize.c ├── BasicTriangle.c ├── Clear3DSlice.c ├── BlitMirror.c ├── BasicVertexBuffer.c ├── TriangleMSAA.c ├── main.c ├── Latency.c ├── BasicCompute.c ├── InstancedIndexed.c ├── CullMode.c ├── DrawIndirect.c ├── CustomSampling.c ├── PullSpriteBatch.c ├── ComputeSampler.c └── BasicStencil.c └── CMakeLists.txt /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ -------------------------------------------------------------------------------- /Content/Images/cube0.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube0.bmp -------------------------------------------------------------------------------- /Content/Images/cube1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube1.bmp -------------------------------------------------------------------------------- /Content/Images/cube2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube2.bmp -------------------------------------------------------------------------------- /Content/Images/cube3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube3.bmp -------------------------------------------------------------------------------- /Content/Images/cube4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube4.bmp -------------------------------------------------------------------------------- /Content/Images/cube5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube5.bmp -------------------------------------------------------------------------------- /Content/Images/armadillo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/armadillo.png -------------------------------------------------------------------------------- /Content/Images/astc/4x4.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/4x4.astc -------------------------------------------------------------------------------- /Content/Images/astc/5x4.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/5x4.astc -------------------------------------------------------------------------------- /Content/Images/astc/5x5.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/5x5.astc -------------------------------------------------------------------------------- /Content/Images/astc/6x5.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/6x5.astc -------------------------------------------------------------------------------- /Content/Images/astc/6x6.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/6x6.astc -------------------------------------------------------------------------------- /Content/Images/astc/8x5.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/8x5.astc -------------------------------------------------------------------------------- /Content/Images/astc/8x6.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/8x6.astc -------------------------------------------------------------------------------- /Content/Images/astc/8x8.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/8x8.astc -------------------------------------------------------------------------------- /Content/Images/bcn/BC1.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC1.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC2.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC2.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC3.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC3.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC4.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC4.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC5.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC5.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC7.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC7.dds -------------------------------------------------------------------------------- /Content/Images/cube0mip1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube0mip1.bmp -------------------------------------------------------------------------------- /Content/Images/cube1mip1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube1mip1.bmp -------------------------------------------------------------------------------- /Content/Images/cube2mip1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube2mip1.bmp -------------------------------------------------------------------------------- /Content/Images/cube3mip1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/cube3mip1.bmp -------------------------------------------------------------------------------- /Content/Images/latency.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/latency.bmp -------------------------------------------------------------------------------- /Content/Images/memorial.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/memorial.hdr -------------------------------------------------------------------------------- /Content/Images/ravioli.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/ravioli.bmp -------------------------------------------------------------------------------- /Content/Images/astc/10x10.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/10x10.astc -------------------------------------------------------------------------------- /Content/Images/astc/10x5.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/10x5.astc -------------------------------------------------------------------------------- /Content/Images/astc/10x6.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/10x6.astc -------------------------------------------------------------------------------- /Content/Images/astc/10x8.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/10x8.astc -------------------------------------------------------------------------------- /Content/Images/astc/12x10.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/12x10.astc -------------------------------------------------------------------------------- /Content/Images/astc/12x12.astc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/astc/12x12.astc -------------------------------------------------------------------------------- /Content/Images/bcn/BC6H_S.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC6H_S.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC6H_U.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC6H_U.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC1_SRGB.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC1_SRGB.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC2_SRGB.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC2_SRGB.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC3_SRGB.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC3_SRGB.dds -------------------------------------------------------------------------------- /Content/Images/bcn/BC7_SRGB.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/bcn/BC7_SRGB.dds -------------------------------------------------------------------------------- /Content/Images/ravioli_atlas.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/ravioli_atlas.bmp -------------------------------------------------------------------------------- /Content/Images/ravioli_inverted.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Images/ravioli_inverted.bmp -------------------------------------------------------------------------------- /Content/Shaders/Source/SolidColor.frag.hlsl: -------------------------------------------------------------------------------- 1 | float4 main(float4 Color : TEXCOORD0) : SV_Target0 2 | { 3 | return Color; 4 | } 5 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/Skybox.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/Skybox.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/Skybox.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/Skybox.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/Skybox.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/Skybox.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/Skybox.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/Skybox.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/Fullscreen.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/Fullscreen.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/SolidColor.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/SolidColor.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/Fullscreen.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/Fullscreen.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/SolidColor.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/SolidColor.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/DepthOutline.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/DepthOutline.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/FillTexture.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/FillTexture.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/LinearToSRGB.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/LinearToSRGB.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/PositionColor.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/PositionColor.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/RawTriangle.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/RawTriangle.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/SpriteBatch.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/SpriteBatch.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuad.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuad.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuad.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuad.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuad.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuad.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/ToneMapACES.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/ToneMapACES.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/ToneMapHable.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/ToneMapHable.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/DepthOutline.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/DepthOutline.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/FillTexture.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/FillTexture.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/LinearToSRGB.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/LinearToSRGB.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/PositionColor.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/PositionColor.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/RawTriangle.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/RawTriangle.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/SpriteBatch.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/SpriteBatch.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuad.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuad.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuad.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuad.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuad.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuad.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/ToneMapACES.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/ToneMapACES.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/ToneMapHable.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/ToneMapHable.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/CustomSampling.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/CustomSampling.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/GradientTexture.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/GradientTexture.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/LinearToST2084.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/LinearToST2084.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/PullSpriteBatch.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/PullSpriteBatch.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/SolidColorDepth.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/SolidColorDepth.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/ToneMapReinhard.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/ToneMapReinhard.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/CustomSampling.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/CustomSampling.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/GradientTexture.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/GradientTexture.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/LinearToST2084.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/LinearToST2084.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/PullSpriteBatch.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/PullSpriteBatch.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/SolidColorDepth.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/SolidColorDepth.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/ToneMapReinhard.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/ToneMapReinhard.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuadArray.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuadArray.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuadColor.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuadColor.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuadArray.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuadArray.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuadColor.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuadColor.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/PositionColorInstanced.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/PositionColorInstanced.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/PositionColorTransform.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/PositionColorTransform.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuadWithMatrix.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuadWithMatrix.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/PositionColorInstanced.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/PositionColorInstanced.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/PositionColorTransform.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/PositionColorTransform.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuadWithMatrix.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMatrix.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuadColorWithMatrix.vert.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuadColorWithMatrix.vert.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuadColorWithMatrix.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuadColorWithMatrix.vert.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/TexturedQuadWithMultiplyColor.frag.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/TexturedQuadWithMultiplyColor.frag.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/TexturedQuadWithMultiplyColor.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/TexturedQuadWithMultiplyColor.frag.spv -------------------------------------------------------------------------------- /Content/Shaders/Compiled/DXIL/ToneMapExtendedReinhardLuminance.comp.dxil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/DXIL/ToneMapExtendedReinhardLuminance.comp.dxil -------------------------------------------------------------------------------- /Content/Shaders/Compiled/SPIRV/ToneMapExtendedReinhardLuminance.comp.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSpydog/SDL_gpu_examples/HEAD/Content/Shaders/Compiled/SPIRV/ToneMapExtendedReinhardLuminance.comp.spv -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuad.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D Texture : register(t0, space2); 2 | SamplerState Sampler : register(s0, space2); 3 | 4 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0 5 | { 6 | return Texture.Sample(Sampler, TexCoord); 7 | } 8 | -------------------------------------------------------------------------------- /Content/Shaders/Source/Skybox.frag.hlsl: -------------------------------------------------------------------------------- 1 | TextureCube SkyboxTexture : register(t0, space2); 2 | SamplerState SkyboxSampler : register(s0, space2); 3 | 4 | float4 main(float3 TexCoord : TEXCOORD0) : SV_Target0 5 | { 6 | return SkyboxTexture.Sample(SkyboxSampler, TexCoord); 7 | } 8 | -------------------------------------------------------------------------------- /Content/Shaders/Source/FillTexture.comp.hlsl: -------------------------------------------------------------------------------- 1 | [[vk::image_format("rgba8")]] 2 | RWTexture2D outImage : register(u0, space1); 3 | 4 | [numthreads(8, 8, 1)] 5 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 6 | { 7 | int2 coord = int2(GlobalInvocationID.xy); 8 | outImage[coord] = float4(1.0f, 1.0f, 0.0f, 1.0f); 9 | } 10 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuadArray.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2DArray Texture : register(t0, space2); 2 | SamplerState Sampler : register(s0, space2); 3 | 4 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0 5 | { 6 | uint arrayIndex = uint(int(TexCoord.y > 0.5f)); 7 | return Texture.Sample(Sampler, float3(TexCoord, float(arrayIndex))); 8 | } 9 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/FillTexture.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d outImage [[texture(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | outImage.write(float4(1.0, 1.0, 0.0, 1.0), uint2(uint2(int2(gl_GlobalInvocationID.xy)))); 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuadColor.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D Texture : register(t0, space2); 2 | SamplerState Sampler : register(s0, space2); 3 | 4 | struct Input 5 | { 6 | float2 TexCoord : TEXCOORD0; 7 | float4 Color : TEXCOORD1; 8 | }; 9 | 10 | float4 main(Input input) : SV_Target0 11 | { 12 | return input.Color * Texture.Sample(Sampler, input.TexCoord); 13 | } 14 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuadWithMultiplyColor.frag.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UniformBlock : register(b0, space3) 2 | { 3 | float4 MultiplyColor : packoffset(c0); 4 | }; 5 | 6 | Texture2D Texture : register(t0, space2); 7 | SamplerState Sampler : register(s0, space2); 8 | 9 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0 10 | { 11 | return MultiplyColor * Texture.Sample(Sampler, TexCoord); 12 | } 13 | -------------------------------------------------------------------------------- /Content/Shaders/Source/PositionColor.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct Input 2 | { 3 | float3 Position : TEXCOORD0; 4 | float4 Color : TEXCOORD1; 5 | }; 6 | 7 | struct Output 8 | { 9 | float4 Color : TEXCOORD0; 10 | float4 Position : SV_Position; 11 | }; 12 | 13 | Output main(Input input) 14 | { 15 | Output output; 16 | output.Color = input.Color; 17 | output.Position = float4(input.Position, 1.0f); 18 | return output; 19 | } 20 | -------------------------------------------------------------------------------- /Content/Shaders/Source/Fullscreen.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct Output 2 | { 3 | float2 TexCoord : TEXCOORD0; 4 | float4 Position : SV_Position; 5 | }; 6 | 7 | Output main(uint VertexIndex : SV_VertexID) 8 | { 9 | Output output; 10 | output.TexCoord = float2(float((VertexIndex << 1) & 2), float(VertexIndex & 2)); 11 | output.Position = float4((output.TexCoord * float2(2.0f, -2.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f); 12 | return output; 13 | } 14 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuad.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct Input 2 | { 3 | float3 Position : TEXCOORD0; 4 | float2 TexCoord : TEXCOORD1; 5 | }; 6 | 7 | struct Output 8 | { 9 | float2 TexCoord : TEXCOORD0; 10 | float4 Position : SV_Position; 11 | }; 12 | 13 | Output main(Input input) 14 | { 15 | Output output; 16 | output.TexCoord = input.TexCoord; 17 | output.Position = float4(input.Position, 1.0f); 18 | return output; 19 | } 20 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/SolidColor.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float4 in_var_TEXCOORD0 [[user(locn0)]]; 14 | }; 15 | 16 | fragment main0_out main0(main0_in in [[stage_in]]) 17 | { 18 | main0_out out = {}; 19 | out.out_var_SV_Target0 = in.in_var_TEXCOORD0; 20 | return out; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/LinearToSRGB.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d InImage [[texture(0)]], texture2d OutImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _29 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | OutImage.write(float4(powr(abs(InImage.read(uint2(_29), 0u).xyz), float3(0.454545438289642333984375)), 1.0), uint2(_29)); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/ToneMapReinhard.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _27 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | float3 _30 = inImage.read(uint2(_27), 0u).xyz; 10 | outImage.write(float4(_30 / (float3(1.0) + _30), 1.0), uint2(_27)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Content/Shaders/Source/PositionColorTransform.vert.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UBO : register(b0, space1) 2 | { 3 | float4x4 transform : packoffset(c0); 4 | }; 5 | 6 | struct Input 7 | { 8 | float3 Position : TEXCOORD0; 9 | float4 Color : TEXCOORD1; 10 | }; 11 | 12 | struct Output 13 | { 14 | float4 Color : TEXCOORD0; 15 | float4 Position : SV_Position; 16 | }; 17 | 18 | Output main(Input input) 19 | { 20 | Output output; 21 | output.Color = input.Color; 22 | output.Position = mul(transform, float4(input.Position, 1.0f)); 23 | return output; 24 | } 25 | -------------------------------------------------------------------------------- /Content/Shaders/Source/ToneMapReinhard.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D inImage : register(t0, space0); 2 | [[vk::image_format("rgba16f")]] 3 | RWTexture2D outImage : register(u0, space1); 4 | 5 | float3 reinhard(float3 v) 6 | { 7 | return v / (1.0f.xxx + v); 8 | } 9 | 10 | [numthreads(8, 8, 1)] 11 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 12 | { 13 | int2 coord = int2(GlobalInvocationID.xy); 14 | float4 inPixel = inImage[coord]; 15 | float3 outColor = reinhard(inPixel.xyz); 16 | outImage[coord] = float4(outColor, 1.0f); 17 | } 18 | -------------------------------------------------------------------------------- /Content/Shaders/Source/Skybox.vert.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UniformBlock : register(b0, space1) 2 | { 3 | float4x4 MatrixTransform : packoffset(c0); 4 | }; 5 | 6 | struct SPIRV_Cross_Input 7 | { 8 | float3 inTexCoord : TEXCOORD0; 9 | }; 10 | 11 | struct Output 12 | { 13 | float3 TexCoord : TEXCOORD0; 14 | float4 Position : SV_Position; 15 | }; 16 | 17 | Output main(float3 inTexCoord : TEXCOORD0) 18 | { 19 | Output output; 20 | output.TexCoord = inTexCoord; 21 | output.Position = mul(MatrixTransform, float4(inTexCoord, 1.0)); 22 | return output; 23 | } 24 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuad.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 14 | }; 15 | 16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]]) 17 | { 18 | main0_out out = {}; 19 | out.out_var_SV_Target0 = Texture.sample(Sampler, in.in_var_TEXCOORD0); 20 | return out; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuadWithMatrix.vert.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UniformBlock : register(b0, space1) 2 | { 3 | float4x4 MatrixTransform : packoffset(c0); 4 | }; 5 | 6 | struct Input 7 | { 8 | float4 Position : TEXCOORD0; 9 | float2 TexCoord : TEXCOORD1; 10 | }; 11 | 12 | struct Output 13 | { 14 | float2 TexCoord : TEXCOORD0; 15 | float4 Position : SV_Position; 16 | }; 17 | 18 | Output main(Input input) 19 | { 20 | Output output; 21 | output.TexCoord = input.TexCoord; 22 | output.Position = mul(MatrixTransform, input.Position); 23 | return output; 24 | } 25 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/Skybox.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float3 in_var_TEXCOORD0 [[user(locn0)]]; 14 | }; 15 | 16 | fragment main0_out main0(main0_in in [[stage_in]], texturecube SkyboxTexture [[texture(0)]], sampler SkyboxSampler [[sampler(0)]]) 17 | { 18 | main0_out out = {}; 19 | out.out_var_SV_Target0 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0); 20 | return out; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/Fullscreen.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float2 out_var_TEXCOORD0 [[user(locn0)]]; 9 | float4 gl_Position [[position]]; 10 | }; 11 | 12 | vertex main0_out main0(uint gl_VertexIndex [[vertex_id]]) 13 | { 14 | main0_out out = {}; 15 | float2 _30 = float2(float((gl_VertexIndex << 1u) & 2u), float(gl_VertexIndex & 2u)); 16 | out.out_var_TEXCOORD0 = _30; 17 | out.gl_Position = float4((_30 * float2(2.0, -2.0)) + float2(-1.0, 1.0), 0.0, 1.0); 18 | return out; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Content/Shaders/Source/LinearToSRGB.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D InImage : register(t0, space0); 2 | [[vk::image_format("rgba8")]] 3 | RWTexture2D OutImage : register(u0, space1); 4 | 5 | float3 LinearToSRGB(float3 color) 6 | { 7 | return pow(abs(color), float(1.0f/2.2f).xxx); 8 | } 9 | 10 | [numthreads(8, 8, 1)] 11 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 12 | { 13 | int2 coord = int2(GlobalInvocationID.xy); 14 | float4 inPixel = InImage[coord]; 15 | float3 param = inPixel.xyz; 16 | float3 outColor = LinearToSRGB(param); 17 | OutImage[coord] = float4(outColor, 1.0f); 18 | } 19 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/PositionColor.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_TEXCOORD0 [[user(locn0)]]; 9 | float4 gl_Position [[position]]; 10 | }; 11 | 12 | struct main0_in 13 | { 14 | float3 in_var_TEXCOORD0 [[attribute(0)]]; 15 | float4 in_var_TEXCOORD1 [[attribute(1)]]; 16 | }; 17 | 18 | vertex main0_out main0(main0_in in [[stage_in]]) 19 | { 20 | main0_out out = {}; 21 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 22 | out.gl_Position = float4(in.in_var_TEXCOORD0, 1.0); 23 | return out; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuad.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float2 out_var_TEXCOORD0 [[user(locn0)]]; 9 | float4 gl_Position [[position]]; 10 | }; 11 | 12 | struct main0_in 13 | { 14 | float3 in_var_TEXCOORD0 [[attribute(0)]]; 15 | float2 in_var_TEXCOORD1 [[attribute(1)]]; 16 | }; 17 | 18 | vertex main0_out main0(main0_in in [[stage_in]]) 19 | { 20 | main0_out out = {}; 21 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 22 | out.gl_Position = float4(in.in_var_TEXCOORD0, 1.0); 23 | return out; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuadColor.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 14 | float4 in_var_TEXCOORD1 [[user(locn1)]]; 15 | }; 16 | 17 | fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]]) 18 | { 19 | main0_out out = {}; 20 | out.out_var_SV_Target0 = in.in_var_TEXCOORD1 * Texture.sample(Sampler, in.in_var_TEXCOORD0); 21 | return out; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Content/Shaders/Source/GradientTexture.comp.hlsl: -------------------------------------------------------------------------------- 1 | [[vk::image_format("rgba8")]] 2 | RWTexture2D OutImage : register(u0, space1); 3 | 4 | cbuffer UBO : register(b0, space2) 5 | { 6 | float ubo_time : packoffset(c0); 7 | }; 8 | 9 | [numthreads(8, 8, 1)] 10 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 11 | { 12 | float w, h; 13 | OutImage.GetDimensions(w, h); 14 | float2 size = float2(w, h); 15 | float2 coord = GlobalInvocationID.xy; 16 | float2 uv = coord / size; 17 | 18 | float3 col = 0.5f.xxx + (cos((ubo_time.xxx + uv.xyx) + float3(0.0f, 2.0f, 4.0f)) * 0.5f); 19 | OutImage[int2(coord)] = float4(col, 1.0f); 20 | } 21 | -------------------------------------------------------------------------------- /Content/Shaders/Source/PositionColorInstanced.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct Input 2 | { 3 | float3 Position : TEXCOORD0; 4 | float4 Color : TEXCOORD1; 5 | uint InstanceIndex : SV_InstanceID; 6 | }; 7 | 8 | struct Output 9 | { 10 | float4 Color : TEXCOORD0; 11 | float4 Position : SV_Position; 12 | }; 13 | 14 | Output main(Input input) 15 | { 16 | Output output; 17 | output.Color = input.Color; 18 | float3 pos = (input.Position * 0.25f) - float3(0.75f, 0.75f, 0.0f); 19 | pos.x += (float(input.InstanceIndex % 4) * 0.5f); 20 | pos.y += (floor(float(input.InstanceIndex / 4)) * 0.5f); 21 | output.Position = float4(pos, 1.0f); 22 | return output; 23 | } 24 | -------------------------------------------------------------------------------- /Content/Shaders/Source/SolidColorDepth.frag.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UBO : register(b0, space3) 2 | { 3 | float NearPlane; 4 | float FarPlane; 5 | }; 6 | 7 | struct Output 8 | { 9 | float4 Color : SV_Target0; 10 | float Depth : SV_Depth; 11 | }; 12 | 13 | float LinearizeDepth(float depth, float near, float far) 14 | { 15 | float z = depth * 2.0 - 1.0; 16 | return ((2.0 * near * far) / (far + near - z * (far - near))) / far; 17 | } 18 | 19 | Output main(float4 Color : TEXCOORD0, float4 Position : SV_Position) 20 | { 21 | Output result; 22 | result.Color = Color; 23 | result.Depth = LinearizeDepth(Position.z, NearPlane, FarPlane); 24 | return result; 25 | } 26 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuadColorWithMatrix.vert.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UniformBlock : register(b0, space1) 2 | { 3 | float4x4 MatrixTransform : packoffset(c0); 4 | }; 5 | 6 | struct Input 7 | { 8 | float4 Position : TEXCOORD0; 9 | float2 TexCoord : TEXCOORD1; 10 | float4 Color : TEXCOORD2; 11 | }; 12 | 13 | struct Output 14 | { 15 | float2 TexCoord : TEXCOORD0; 16 | float4 Color : TEXCOORD1; 17 | float4 Position : SV_Position; 18 | }; 19 | 20 | Output main(Input input) 21 | { 22 | Output output; 23 | output.TexCoord = input.TexCoord; 24 | output.Color = input.Color; 25 | output.Position = mul(MatrixTransform, input.Position); 26 | return output; 27 | } 28 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuadArray.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 14 | }; 15 | 16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d_array Texture [[texture(0)]], sampler Sampler [[sampler(0)]]) 17 | { 18 | main0_out out = {}; 19 | float3 _38 = float3(in.in_var_TEXCOORD0, float(uint(int(in.in_var_TEXCOORD0.y > 0.5)))); 20 | out.out_var_SV_Target0 = Texture.sample(Sampler, _38.xy, uint(rint(_38.z))); 21 | return out; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/GradientTexture.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UBO 7 | { 8 | float ubo_time; 9 | }; 10 | 11 | kernel void main0(constant type_UBO& UBO [[buffer(0)]], texture2d OutImage [[texture(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 12 | { 13 | uint2 _34 = uint2(OutImage.get_width(), OutImage.get_height()); 14 | float2 _41 = float2(gl_GlobalInvocationID.xy); 15 | OutImage.write(float4(float3(0.5) + (cos((float3(UBO.ubo_time) + (_41 / float2(float(_34.x), float(_34.y))).xyx) + float3(0.0, 2.0, 4.0)) * 0.5), 1.0), uint2(uint2(int2(_41)))); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/ToneMapExtendedReinhardLuminance.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _31 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | float3 _34 = inImage.read(uint2(_31), 0u).xyz; 10 | float _35 = dot(_34, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); 11 | outImage.write(float4(_34 * (((_35 * (1.0 + (_35 * 2.2818337583885295316576957702637e-06))) / (1.0 + _35)) / _35), 1.0), uint2(_31)); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/Skybox.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UniformBlock 7 | { 8 | float4x4 MatrixTransform; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float3 out_var_TEXCOORD0 [[user(locn0)]]; 14 | float4 gl_Position [[position]]; 15 | }; 16 | 17 | struct main0_in 18 | { 19 | float3 in_var_TEXCOORD0 [[attribute(0)]]; 20 | }; 21 | 22 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]]) 23 | { 24 | main0_out out = {}; 25 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD0; 26 | out.gl_Position = UniformBlock.MatrixTransform * float4(in.in_var_TEXCOORD0, 1.0); 27 | return out; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuadWithMultiplyColor.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UniformBlock 7 | { 8 | float4 MultiplyColor; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float4 out_var_SV_Target0 [[color(0)]]; 14 | }; 15 | 16 | struct main0_in 17 | { 18 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 19 | }; 20 | 21 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]], texture2d Texture [[texture(0)]], sampler Sampler [[sampler(0)]]) 22 | { 23 | main0_out out = {}; 24 | out.out_var_SV_Target0 = UniformBlock.MultiplyColor * Texture.sample(Sampler, in.in_var_TEXCOORD0); 25 | return out; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /Content/Shaders/Source/TexturedQuad.comp.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UBO : register(b0, space2) 2 | { 3 | float ubo_texcoord_multiplier : packoffset(c0); 4 | }; 5 | 6 | Texture2D inImage : register(t0, space0); 7 | SamplerState inImageSampler : register(s0, space0); 8 | 9 | [[vk::image_format("rgba8")]] 10 | RWTexture2D outImage : register(u0, space1); 11 | 12 | [numthreads(8, 8, 1)] 13 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 14 | { 15 | float w, h; 16 | inImage.GetDimensions(w, h); 17 | int2 coord = int2(GlobalInvocationID.xy); 18 | float2 texcoord = (float2(coord) * ubo_texcoord_multiplier) / float2(w, h); 19 | float4 inPixel = inImage.SampleLevel(inImageSampler, texcoord, 0.0f); 20 | outImage[coord] = inPixel; 21 | } 22 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/PositionColorTransform.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UBO 7 | { 8 | float4x4 transform; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float4 out_var_TEXCOORD0 [[user(locn0)]]; 14 | float4 gl_Position [[position]]; 15 | }; 16 | 17 | struct main0_in 18 | { 19 | float3 in_var_TEXCOORD0 [[attribute(0)]]; 20 | float4 in_var_TEXCOORD1 [[attribute(1)]]; 21 | }; 22 | 23 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]]) 24 | { 25 | main0_out out = {}; 26 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 27 | out.gl_Position = UBO.transform * float4(in.in_var_TEXCOORD0, 1.0); 28 | return out; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuad.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UBO 7 | { 8 | float ubo_texcoord_multiplier; 9 | }; 10 | 11 | kernel void main0(constant type_UBO& UBO [[buffer(0)]], texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], sampler inImageSampler [[sampler(0)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 12 | { 13 | uint2 _33 = uint2(inImage.get_width(), inImage.get_height()); 14 | int2 _39 = int2(gl_GlobalInvocationID.xy); 15 | outImage.write(inImage.sample(inImageSampler, ((float2(_39) * UBO.ubo_texcoord_multiplier) / float2(float(_33.x), float(_33.y))), level(0.0)), uint2(uint2(_39))); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/ToneMapHable.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _40 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | float3 _44 = inImage.read(uint2(_40), 0u).xyz * 2.0; 10 | float3 _45 = _44 * 0.1500000059604644775390625; 11 | outImage.write(float4(((((_44 * (_45 + float3(0.0500000007450580596923828125))) + float3(0.0040000001899898052215576171875)) / ((_44 * (_45 + float3(0.5))) + float3(0.060000002384185791015625))) - float3(0.066666662693023681640625)) * float3(1.3790643215179443359375), 1.0), uint2(_40)); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Collection of examples to demonstrate the usage of the SDL_GPU API. 2 | 3 | To clone and build: 4 | ``` 5 | git clone https://github.com/libsdl-org/SDL 6 | cd SDL 7 | mkdir build 8 | cd build 9 | cmake .. 10 | 11 | cd ../.. 12 | git clone https://github.com/TheSpydog/SDL_gpu_examples 13 | cd SDL_gpu_examples 14 | mkdir build 15 | cd build 16 | cmake .. -DSDL3_DIR="full/path/to/SDL/build" 17 | ``` 18 | then run `make` or your favorite IDE. 19 | 20 | The shaders in the repository are written in HLSL and offline compiled from `Content/Shaders/Source` to `Content/Shaders/Compiled` using [SDL_shadercross](https://github.com/libsdl-org/SDL_shadercross). If you want to build the shaders yourself, you must install `SDL_shadercross`, navigate to the shader source directory, and call `compile.sh`. 21 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuadWithMatrix.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UniformBlock 7 | { 8 | float4x4 MatrixTransform; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float2 out_var_TEXCOORD0 [[user(locn0)]]; 14 | float4 gl_Position [[position]]; 15 | }; 16 | 17 | struct main0_in 18 | { 19 | float4 in_var_TEXCOORD0 [[attribute(0)]]; 20 | float2 in_var_TEXCOORD1 [[attribute(1)]]; 21 | }; 22 | 23 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]]) 24 | { 25 | main0_out out = {}; 26 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 27 | out.gl_Position = UniformBlock.MatrixTransform * in.in_var_TEXCOORD0; 28 | return out; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/PositionColorInstanced.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_TEXCOORD0 [[user(locn0)]]; 9 | float4 gl_Position [[position]]; 10 | }; 11 | 12 | struct main0_in 13 | { 14 | float3 in_var_TEXCOORD0 [[attribute(0)]]; 15 | float4 in_var_TEXCOORD1 [[attribute(1)]]; 16 | }; 17 | 18 | vertex main0_out main0(main0_in in [[stage_in]], uint gl_InstanceIndex [[instance_id]]) 19 | { 20 | main0_out out = {}; 21 | float3 _30 = (in.in_var_TEXCOORD0 * 0.25) - float3(0.75, 0.75, 0.0); 22 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 23 | out.gl_Position = float4(_30.x + (float(gl_InstanceIndex % 4u) * 0.5), _30.y + (floor(float(gl_InstanceIndex / 4u)) * 0.5), _30.z, 1.0); 24 | return out; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/SolidColorDepth.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UBO 7 | { 8 | float NearPlane; 9 | float FarPlane; 10 | }; 11 | 12 | struct main0_out 13 | { 14 | float4 out_var_SV_Target0 [[color(0)]]; 15 | float gl_FragDepth [[depth(any)]]; 16 | }; 17 | 18 | struct main0_in 19 | { 20 | float4 in_var_TEXCOORD0 [[user(locn0)]]; 21 | }; 22 | 23 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]], float4 gl_FragCoord [[position]]) 24 | { 25 | main0_out out = {}; 26 | out.out_var_SV_Target0 = in.in_var_TEXCOORD0; 27 | out.gl_FragDepth = (((2.0 * UBO.NearPlane) * UBO.FarPlane) / ((UBO.FarPlane + UBO.NearPlane) - (((gl_FragCoord.z * 2.0) - 1.0) * (UBO.FarPlane - UBO.NearPlane)))) / UBO.FarPlane; 28 | return out; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2024 Caleb Cornett 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/TexturedQuadColorWithMatrix.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UniformBlock 7 | { 8 | float4x4 MatrixTransform; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float2 out_var_TEXCOORD0 [[user(locn0)]]; 14 | float4 out_var_TEXCOORD1 [[user(locn1)]]; 15 | float4 gl_Position [[position]]; 16 | }; 17 | 18 | struct main0_in 19 | { 20 | float4 in_var_TEXCOORD0 [[attribute(0)]]; 21 | float2 in_var_TEXCOORD1 [[attribute(1)]]; 22 | float4 in_var_TEXCOORD2 [[attribute(2)]]; 23 | }; 24 | 25 | vertex main0_out main0(main0_in in [[stage_in]], constant type_UniformBlock& UniformBlock [[buffer(0)]]) 26 | { 27 | main0_out out = {}; 28 | out.out_var_TEXCOORD0 = in.in_var_TEXCOORD1; 29 | out.out_var_TEXCOORD1 = in.in_var_TEXCOORD2; 30 | out.gl_Position = UniformBlock.MatrixTransform * in.in_var_TEXCOORD0; 31 | return out; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Content/Shaders/Source/CustomSampling.frag.hlsl: -------------------------------------------------------------------------------- 1 | cbuffer UBO : register(b0, space3) 2 | { 3 | int mode : packoffset(c0); 4 | }; 5 | 6 | Texture2D Texture : register(t0, space2); 7 | 8 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0 9 | { 10 | float w, h; 11 | Texture.GetDimensions(w, h); 12 | int2 texelPos = int2(float2(w, h) * TexCoord); 13 | float4 mainTexel = Texture[texelPos]; 14 | if (mode == 0) 15 | { 16 | return mainTexel; 17 | } 18 | else 19 | { 20 | float4 bottomTexel = Texture[texelPos + int2(0, 1)]; 21 | float4 leftTexel = Texture[texelPos + int2(-1, 0)]; 22 | float4 topTexel = Texture[texelPos + int2(0, -1)]; 23 | float4 rightTexel = Texture[texelPos + int2(1, 0)]; 24 | return ((((mainTexel * 0.2f) + (bottomTexel * 0.2f)) + (leftTexel * 0.20000000298023223876953125f)) + (topTexel * 0.20000000298023223876953125f)) + (rightTexel * 0.2f); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Content/Shaders/Source/RawTriangle.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct Input 2 | { 3 | uint VertexIndex : SV_VertexID; 4 | }; 5 | 6 | struct Output 7 | { 8 | float4 Color : TEXCOORD0; 9 | float4 Position : SV_Position; 10 | }; 11 | 12 | Output main(Input input) 13 | { 14 | Output output; 15 | float2 pos; 16 | if (input.VertexIndex == 0) 17 | { 18 | pos = (-1.0f).xx; 19 | output.Color = float4(1.0f, 0.0f, 0.0f, 1.0f); 20 | } 21 | else 22 | { 23 | if (input.VertexIndex == 1) 24 | { 25 | pos = float2(1.0f, -1.0f); 26 | output.Color = float4(0.0f, 1.0f, 0.0f, 1.0f); 27 | } 28 | else 29 | { 30 | if (input.VertexIndex == 2) 31 | { 32 | pos = float2(0.0f, 1.0f); 33 | output.Color = float4(0.0f, 0.0f, 1.0f, 1.0f); 34 | } 35 | } 36 | } 37 | output.Position = float4(pos, 0.0f, 1.0f); 38 | return output; 39 | } 40 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/LinearToST2084.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d InImage [[texture(0)]], texture2d OutImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _53 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | float4 _55 = InImage.read(uint2(_53), 0u); 10 | float3 _61 = powr(abs(((_55.xyz * float3x3(float3(0.6274039745330810546875, 0.329281985759735107421875, 0.043313600122928619384765625), float3(0.06909699738025665283203125, 0.919539988040924072265625, 0.0113612003624439239501953125), float3(0.01639159955084323883056640625, 0.0880132019519805908203125, 0.895595014095306396484375))) * 200.0) * float3(9.9999997473787516355514526367188e-05)), float3(0.1593017578125)); 11 | OutImage.write(float4(powr((float3(0.8359375) + (_61 * 18.8515625)) / (float3(1.0) + (_61 * 18.6875)), float3(78.84375)), _55.w), uint2(_53)); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Content/Shaders/Source/ToneMapACES.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D inImage : register(t0, space0); 2 | [[vk::image_format("rgba16f")]] 3 | RWTexture2D outImage : register(u0, space1); 4 | 5 | float3 rtt_and_odt_fit(float3 v) 6 | { 7 | float3 a = (v * (v + 0.0245786f.xxx)) - 0.000090537f.xxx; 8 | float3 b = (v * ((v * 0.983729f) + 0.4329510f.xxx)) + 0.238081f.xxx; 9 | return a / b; 10 | } 11 | 12 | float3 aces_fitted(float3 v) 13 | { 14 | v = mul(float3x3(float3(0.59719f, 0.35458f, 0.04823f), float3(0.07600f, 0.90834f, 0.01566f), float3(0.02840f, 0.13383f, 0.83777f)), v); 15 | v = rtt_and_odt_fit(v); 16 | return mul(float3x3(float3(1.60475f, -0.53108f, -0.07367f), float3(-0.10208f, 1.10813f, -0.00605f), float3(-0.00327f, -0.07276f, 1.07602f)), v); 17 | } 18 | 19 | [numthreads(8, 8, 1)] 20 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 21 | { 22 | int2 coord = int2(GlobalInvocationID.xy); 23 | float4 inPixel = inImage[coord]; 24 | float3 outColor = aces_fitted(inPixel.xyz); 25 | outImage[coord] = float4(outColor, 1.0f); 26 | } 27 | -------------------------------------------------------------------------------- /Content/Shaders/Source/ToneMapExtendedReinhardLuminance.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D inImage : register(t0, space0); 2 | [[vk::image_format("rgba16f")]] 3 | RWTexture2D outImage : register(u0, space1); 4 | 5 | float luminance(float3 v) 6 | { 7 | return dot(v, float3(0.2126f, 0.7152f, 0.0722f)); 8 | } 9 | 10 | float3 change_luminance(float3 c_in, float l_out) 11 | { 12 | float l_in = luminance(c_in); 13 | return c_in * (l_out / l_in); 14 | } 15 | 16 | float3 reinhard_extended_luminance(float3 v, float max_white_l) 17 | { 18 | float l_old = luminance(v); 19 | float numerator = l_old * (1.0f + (l_old / (max_white_l * max_white_l))); 20 | float l_new = numerator / (1.0f + l_old); 21 | return change_luminance(v, l_new); 22 | } 23 | 24 | [numthreads(8, 8, 1)] 25 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 26 | { 27 | int2 coord = int2(GlobalInvocationID.xy); 28 | float4 inPixel = inImage[coord]; 29 | float3 outColor = reinhard_extended_luminance(inPixel.xyz, 662.0f); 30 | outImage[coord] = float4(outColor, 1.0f); 31 | } 32 | -------------------------------------------------------------------------------- /Content/Shaders/Source/compile.sh: -------------------------------------------------------------------------------- 1 | # Requires shadercross CLI installed from SDL_shadercross 2 | for filename in *.vert.hlsl; do 3 | if [ -f "$filename" ]; then 4 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}" 5 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}" 6 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}" 7 | fi 8 | done 9 | 10 | for filename in *.frag.hlsl; do 11 | if [ -f "$filename" ]; then 12 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}" 13 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}" 14 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}" 15 | fi 16 | done 17 | 18 | for filename in *.comp.hlsl; do 19 | if [ -f "$filename" ]; then 20 | shadercross "$filename" -o "../Compiled/SPIRV/${filename/.hlsl/.spv}" 21 | shadercross "$filename" -o "../Compiled/MSL/${filename/.hlsl/.msl}" 22 | shadercross "$filename" -o "../Compiled/DXIL/${filename/.hlsl/.dxil}" 23 | fi 24 | done 25 | -------------------------------------------------------------------------------- /Content/Shaders/Source/ToneMapHable.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D inImage : register(t0, space0); 2 | [[vk::image_format("rgba16f")]] 3 | RWTexture2D outImage : register(u0, space1); 4 | 5 | float3 hable_tonemap_partial(float3 x) 6 | { 7 | float A = 0.15f; 8 | float B = 0.50f; 9 | float C = 0.10f; 10 | float D = 0.20f; 11 | float E = 0.02f; 12 | float F = 0.30f; 13 | return (((x * ((x * A) + (C * B).xxx)) + (D * E).xxx) / ((x * ((x * A) + B.xxx)) + (D * F).xxx)) - (E / F).xxx; 14 | } 15 | 16 | float3 hable_filmic(float3 v) 17 | { 18 | float exposure_bias = 2.0f; 19 | float3 curr = hable_tonemap_partial(v * exposure_bias); 20 | 21 | float3 W = 11.2f.xxx; 22 | float3 white_scale = 1.0f.xxx / hable_tonemap_partial(W); 23 | return curr * white_scale; 24 | } 25 | 26 | [numthreads(8, 8, 1)] 27 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 28 | { 29 | int2 coord = int2(GlobalInvocationID.xy); 30 | float4 inPixel = inImage[coord]; 31 | float3 outColor = hable_filmic(inPixel.xyz); 32 | outImage[coord] = float4(outColor, 1.0f); 33 | } 34 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/RawTriangle.vert.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | constant float2 _25 = {}; 7 | constant float4 _26 = {}; 8 | 9 | struct main0_out 10 | { 11 | float4 out_var_TEXCOORD0 [[user(locn0)]]; 12 | float4 gl_Position [[position]]; 13 | }; 14 | 15 | vertex main0_out main0(uint gl_VertexIndex [[vertex_id]]) 16 | { 17 | main0_out out = {}; 18 | float4 _47; 19 | float2 _48; 20 | if (gl_VertexIndex == 0u) 21 | { 22 | _47 = float4(1.0, 0.0, 0.0, 1.0); 23 | _48 = float2(-1.0); 24 | } 25 | else 26 | { 27 | float4 _45; 28 | float2 _46; 29 | if (gl_VertexIndex == 1u) 30 | { 31 | _45 = float4(0.0, 1.0, 0.0, 1.0); 32 | _46 = float2(1.0, -1.0); 33 | } 34 | else 35 | { 36 | bool _40 = gl_VertexIndex == 2u; 37 | _45 = select(_26, float4(0.0, 0.0, 1.0, 1.0), bool4(_40)); 38 | _46 = select(_25, float2(0.0, 1.0), bool2(_40)); 39 | } 40 | _47 = _45; 41 | _48 = _46; 42 | } 43 | out.out_var_TEXCOORD0 = _47; 44 | out.gl_Position = float4(_48, 0.0, 1.0); 45 | return out; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/ToneMapACES.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | kernel void main0(texture2d inImage [[texture(0)]], texture2d outImage [[texture(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 7 | { 8 | uint2 _62 = uint2(int2(gl_GlobalInvocationID.xy)); 9 | float3 _66 = inImage.read(uint2(_62), 0u).xyz * float3x3(float3(0.59719002246856689453125, 0.354579985141754150390625, 0.048229999840259552001953125), float3(0.075999997556209564208984375, 0.908339977264404296875, 0.0156599991023540496826171875), float3(0.0284000001847743988037109375, 0.13382999598979949951171875, 0.837769985198974609375)); 10 | outImage.write(float4((((_66 * (_66 + float3(0.02457859925925731658935546875))) - float3(9.0537003416102379560470581054688e-05)) / ((_66 * ((_66 * 0.98372900485992431640625) + float3(0.4329510033130645751953125))) + float3(0.23808099329471588134765625))) * float3x3(float3(1.60475003719329833984375, -0.5310800075531005859375, -0.0736699998378753662109375), float3(-0.10208000242710113525390625, 1.108129978179931640625, -0.00604999996721744537353515625), float3(-0.00326999998651444911956787109375, -0.07276000082492828369140625, 1.0760200023651123046875)), 1.0), uint2(_62)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Content/Shaders/Source/LinearToST2084.comp.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D InImage : register(t0, space0); 2 | [[vk::image_format("rgba8")]] 3 | RWTexture2D OutImage : register(u0, space1); 4 | 5 | float3 NormalizeHDRSceneValue(float3 hdrSceneValue, float paperWhiteNits) 6 | { 7 | return (hdrSceneValue * paperWhiteNits) / 10000.0f.xxx; 8 | } 9 | 10 | float3 LinearToST2084(float3 normalizedLinearValue) 11 | { 12 | return pow((0.8359375f.xxx + (pow(abs(normalizedLinearValue), 0.1593017578125f.xxx) * 18.8515625f)) / (1.0f.xxx + (pow(abs(normalizedLinearValue), 0.1593017578125f.xxx) * 18.6875f)), 78.84375f.xxx); 13 | } 14 | 15 | float4 ConvertToHDR10(float4 hdrSceneValue, float paperWhiteNits) 16 | { 17 | float3 rec2020 = mul(float3x3(float3(0.6274039745330810546875f, 0.329281985759735107421875f, 0.043313600122928619384765625f), float3(0.06909699738025665283203125f, 0.919539988040924072265625f, 0.0113612003624439239501953125f), float3(0.01639159955084323883056640625f, 0.0880132019519805908203125f, 0.895595014095306396484375f)), hdrSceneValue.xyz); 18 | float3 normalizedLinearValue = NormalizeHDRSceneValue(rec2020, paperWhiteNits); 19 | float3 HDR10 = LinearToST2084(normalizedLinearValue); 20 | return float4(HDR10, hdrSceneValue.w); 21 | } 22 | 23 | [numthreads(8, 8, 1)] 24 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 25 | { 26 | int2 coord = int2(GlobalInvocationID.xy); 27 | float4 inPixel = InImage[coord]; 28 | OutImage[coord] = ConvertToHDR10(inPixel, 200.0f); 29 | } 30 | -------------------------------------------------------------------------------- /Examples/ClearScreen.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static int Init(Context* context) 4 | { 5 | return CommonInit(context, SDL_WINDOW_RESIZABLE); 6 | } 7 | 8 | static int Update(Context* context) 9 | { 10 | return 0; 11 | } 12 | 13 | static int Draw(Context* context) 14 | { 15 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 16 | if (cmdbuf == NULL) 17 | { 18 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 19 | return -1; 20 | } 21 | 22 | SDL_GPUTexture* swapchainTexture; 23 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 24 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 25 | return -1; 26 | } 27 | 28 | if (swapchainTexture != NULL) 29 | { 30 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 31 | colorTargetInfo.texture = swapchainTexture; 32 | colorTargetInfo.clear_color = (SDL_FColor){ 0.3f, 0.4f, 0.5f, 1.0f }; 33 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 34 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 35 | 36 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 37 | SDL_EndGPURenderPass(renderPass); 38 | } 39 | 40 | SDL_SubmitGPUCommandBuffer(cmdbuf); 41 | 42 | return 0; 43 | } 44 | 45 | static void Quit(Context* context) 46 | { 47 | CommonQuit(context); 48 | } 49 | 50 | Example ClearScreen_Example = { "ClearScreen", Init, Update, Draw, Quit }; 51 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/CustomSampling.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct type_UBO 7 | { 8 | int mode; 9 | }; 10 | 11 | struct main0_out 12 | { 13 | float4 out_var_SV_Target0 [[color(0)]]; 14 | }; 15 | 16 | struct main0_in 17 | { 18 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 19 | }; 20 | 21 | fragment main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]], texture2d Texture [[texture(0)]]) 22 | { 23 | main0_out out = {}; 24 | float4 _79; 25 | do 26 | { 27 | uint2 _37 = uint2(Texture.get_width(), Texture.get_height()); 28 | int2 _44 = int2(float2(float(_37.x), float(_37.y)) * in.in_var_TEXCOORD0); 29 | float4 _47 = Texture.read(uint2(uint2(_44)), 0u); 30 | if (UBO.mode == 0) 31 | { 32 | _79 = _47; 33 | break; 34 | } 35 | else 36 | { 37 | _79 = ((((_47 * 0.20000000298023223876953125) + (Texture.read(uint2(uint2(_44 + int2(0, 1))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(-1, 0))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(0, -1))), 0u) * 0.20000000298023223876953125)) + (Texture.read(uint2(uint2(_44 + int2(1, 0))), 0u) * 0.20000000298023223876953125); 38 | break; 39 | } 40 | break; // unreachable workaround 41 | } while(false); 42 | out.out_var_SV_Target0 = _79; 43 | return out; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(SDL_gpu_examples) 3 | find_package(SDL3 REQUIRED) 4 | 5 | add_executable(SDL_gpu_examples 6 | Examples/main.c 7 | Examples/Common.h 8 | stb_image.h 9 | Examples/Common.c 10 | Examples/ClearScreen.c 11 | Examples/ClearScreenMultiWindow.c 12 | Examples/BasicTriangle.c 13 | Examples/BasicVertexBuffer.c 14 | Examples/CullMode.c 15 | Examples/BasicStencil.c 16 | Examples/InstancedIndexed.c 17 | Examples/TexturedQuad.c 18 | Examples/ComputeSampler.c 19 | Examples/TexturedAnimatedQuad.c 20 | Examples/Clear3DSlice.c 21 | Examples/BasicCompute.c 22 | Examples/ComputeUniforms.c 23 | Examples/ToneMapping.c 24 | Examples/CustomSampling.c 25 | Examples/DrawIndirect.c 26 | Examples/ComputeSpriteBatch.c 27 | Examples/CopyAndReadback.c 28 | Examples/CopyConsistency.c 29 | Examples/Texture2DArray.c 30 | Examples/TriangleMSAA.c 31 | Examples/Cubemap.c 32 | Examples/WindowResize.c 33 | Examples/Blit2DArray.c 34 | Examples/BlitCube.c 35 | Examples/BlitMirror.c 36 | Examples/GenerateMipmaps.c 37 | Examples/Latency.c 38 | Examples/DepthSampler.c 39 | Examples/PullSpriteBatch.c 40 | Examples/TextureTypeTest.c 41 | Examples/CompressedTextures.c 42 | ) 43 | 44 | target_link_libraries(SDL_gpu_examples 45 | SDL3::SDL3 46 | ) 47 | 48 | add_custom_command(TARGET SDL_gpu_examples POST_BUILD 49 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Content $/Content 50 | ) 51 | -------------------------------------------------------------------------------- /Content/Shaders/Source/DepthOutline.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D ColorTexture : register(t0, space2); 2 | SamplerState ColorSampler : register(s0, space2); 3 | 4 | Texture2D DepthTexture : register(t1, space2); 5 | SamplerState DepthSampler : register(s1, space2); 6 | 7 | // Gets the difference between a depth value and adjacent depth pixels 8 | // This is used to detect "edges", where the depth falls off. 9 | float GetDifference(float depth, float2 TexCoord, float distance) 10 | { 11 | float w, h; 12 | DepthTexture.GetDimensions(w, h); 13 | 14 | return 15 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(1.0 / w, 0) * distance).r - depth, 16 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(-1.0 / w, 0) * distance).r - depth, 17 | max(DepthTexture.Sample(DepthSampler, TexCoord + float2(0, 1.0 / h) * distance).r - depth, 18 | DepthTexture.Sample(DepthSampler, TexCoord + float2(0, -1.0 / h) * distance).r - depth))); 19 | } 20 | 21 | float4 main(float2 TexCoord : TEXCOORD0) : SV_Target0 22 | { 23 | // get our color & depth value 24 | float4 color = ColorTexture.Sample(ColorSampler, TexCoord); 25 | float depth = DepthTexture.Sample(DepthSampler, TexCoord).r; 26 | 27 | // get the difference between the edges at 1px and 2px away 28 | float edge = step(0.2, GetDifference(depth, TexCoord, 1.0f)); 29 | float edge2 = step(0.2, GetDifference(depth, TexCoord, 2.0f)); 30 | 31 | // turn inner edges black 32 | float3 res = lerp(color.rgb, 0, edge2); 33 | 34 | // turn the outer edges white 35 | res = lerp(res, 1, edge); 36 | 37 | // combine results 38 | return float4(res, color.a); 39 | } 40 | -------------------------------------------------------------------------------- /Content/Shaders/Source/PullSpriteBatch.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct SpriteData 2 | { 3 | float3 Position; 4 | float Rotation; 5 | float2 Scale; 6 | float2 Padding; 7 | float TexU, TexV, TexW, TexH; 8 | float4 Color; 9 | }; 10 | 11 | struct Output 12 | { 13 | float2 Texcoord : TEXCOORD0; 14 | float4 Color : TEXCOORD1; 15 | float4 Position : SV_Position; 16 | }; 17 | 18 | // WARNING: StructuredBuffers are not natively supported by SDL's GPU API. 19 | // They will work with SDL_shadercross because it does special processing to 20 | // support them, but not with direct compilation via dxc. 21 | // See https://github.com/libsdl-org/SDL/issues/12200 for details. 22 | StructuredBuffer DataBuffer : register(t0, space0); 23 | 24 | cbuffer UniformBlock : register(b0, space1) 25 | { 26 | float4x4 ViewProjectionMatrix : packoffset(c0); 27 | }; 28 | 29 | static const uint triangleIndices[6] = {0, 1, 2, 3, 2, 1}; 30 | static const float2 vertexPos[4] = { 31 | {0.0f, 0.0f}, 32 | {1.0f, 0.0f}, 33 | {0.0f, 1.0f}, 34 | {1.0f, 1.0f} 35 | }; 36 | 37 | Output main(uint id : SV_VertexID) 38 | { 39 | uint spriteIndex = id / 6; 40 | uint vert = triangleIndices[id % 6]; 41 | SpriteData sprite = DataBuffer[spriteIndex]; 42 | 43 | float2 texcoord[4] = { 44 | {sprite.TexU, sprite.TexV }, 45 | {sprite.TexU + sprite.TexW, sprite.TexV }, 46 | {sprite.TexU, sprite.TexV + sprite.TexH}, 47 | {sprite.TexU + sprite.TexW, sprite.TexV + sprite.TexH} 48 | }; 49 | 50 | float c = cos(sprite.Rotation); 51 | float s = sin(sprite.Rotation); 52 | 53 | float2 coord = vertexPos[vert]; 54 | coord *= sprite.Scale; 55 | float2x2 rotation = {c, s, -s, c}; 56 | coord = mul(coord, rotation); 57 | 58 | float3 coordWithDepth = float3(coord + sprite.Position.xy, sprite.Position.z); 59 | 60 | Output output; 61 | 62 | output.Position = mul(ViewProjectionMatrix, float4(coordWithDepth, 1.0f)); 63 | output.Texcoord = texcoord[vert]; 64 | output.Color = sprite.Color; 65 | 66 | return output; 67 | } 68 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/DepthOutline.frag.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct main0_out 7 | { 8 | float4 out_var_SV_Target0 [[color(0)]]; 9 | }; 10 | 11 | struct main0_in 12 | { 13 | float2 in_var_TEXCOORD0 [[user(locn0)]]; 14 | }; 15 | 16 | fragment main0_out main0(main0_in in [[stage_in]], texture2d ColorTexture [[texture(0)]], texture2d DepthTexture [[texture(1)]], sampler ColorSampler [[sampler(0)]], sampler DepthSampler [[sampler(1)]]) 17 | { 18 | main0_out out = {}; 19 | float4 _38 = ColorTexture.sample(ColorSampler, in.in_var_TEXCOORD0); 20 | float4 _42 = DepthTexture.sample(DepthSampler, in.in_var_TEXCOORD0); 21 | float _43 = _42.x; 22 | uint2 _45 = uint2(DepthTexture.get_width(), DepthTexture.get_height()); 23 | float _47 = float(_45.x); 24 | float _49 = float(_45.y); 25 | uint2 _95 = uint2(DepthTexture.get_width(), DepthTexture.get_height()); 26 | float _97 = float(_95.x); 27 | float _99 = float(_95.y); 28 | float3 _148 = mix(mix(_38.xyz, float3(0.0), float3(step(0.20000000298023223876953125, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(1.0 / _97, 0.0) * 2.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2((-1.0) / _97, 0.0) * 2.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(0.0, 1.0 / _99) * 2.0))).x - _43, DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(0.0, (-1.0) / _99) * 2.0))).x - _43)))))), float3(1.0), float3(step(0.20000000298023223876953125, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(1.0 / _47, 0.0) * 1.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2((-1.0) / _47, 0.0) * 1.0))).x - _43, precise::max(DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(0.0, 1.0 / _49) * 1.0))).x - _43, DepthTexture.sample(DepthSampler, (in.in_var_TEXCOORD0 + (float2(0.0, (-1.0) / _49) * 1.0))).x - _43)))))); 29 | out.out_var_SV_Target0 = float4(_148, _38.w); 30 | return out; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Content/Shaders/Source/SpriteBatch.comp.hlsl: -------------------------------------------------------------------------------- 1 | struct SpriteComputeData 2 | { 3 | float3 Position; 4 | float Rotation; 5 | float2 Scale; 6 | float2 Padding; 7 | float TexU, TexV, TexW, TexH; 8 | float4 Color; 9 | }; 10 | 11 | struct SpriteVertex 12 | { 13 | float4 Position; 14 | float2 Texcoord; 15 | float4 Color; 16 | }; 17 | 18 | StructuredBuffer ComputeBuffer : register(t0, space0); 19 | RWStructuredBuffer VertexBuffer : register(u0, space1); 20 | 21 | [numthreads(64, 1, 1)] 22 | void main(uint3 GlobalInvocationID : SV_DispatchThreadID) 23 | { 24 | uint n = GlobalInvocationID.x; 25 | 26 | SpriteComputeData sprite = ComputeBuffer[n]; 27 | 28 | float4x4 Scale = float4x4( 29 | float4(sprite.Scale.x, 0.0f, 0.0f, 0.0f), 30 | float4(0.0f, sprite.Scale.y, 0.0f, 0.0f), 31 | float4(0.0f, 0.0f, 1.0f, 0.0f), 32 | float4(0.0f, 0.0f, 0.0f, 1.0f) 33 | ); 34 | 35 | float c = cos(sprite.Rotation); 36 | float s = sin(sprite.Rotation); 37 | 38 | float4x4 Rotation = float4x4( 39 | float4( c, s, 0.0f, 0.0f), 40 | float4( -s, c, 0.0f, 0.0f), 41 | float4(0.0f, 0.0f, 1.0f, 0.0f), 42 | float4(0.0f, 0.0f, 0.0f, 1.0f) 43 | ); 44 | 45 | float4x4 Translation = float4x4( 46 | float4(1.0f, 0.0f, 0.0f, 0.0f), 47 | float4(0.0f, 1.0f, 0.0f, 0.0f), 48 | float4(0.0f, 0.0f, 1.0f, 0.0f), 49 | float4(sprite.Position.x, sprite.Position.y, sprite.Position.z, 1.0f) 50 | ); 51 | 52 | float4x4 Model = mul(Scale, mul(Rotation, Translation)); 53 | 54 | float4 topLeft = float4(0.0f, 0.0f, 0.0f, 1.0f); 55 | float4 topRight = float4(1.0f, 0.0f, 0.0f, 1.0f); 56 | float4 bottomLeft = float4(0.0f, 1.0f, 0.0f, 1.0f); 57 | float4 bottomRight = float4(1.0f, 1.0f, 0.0f, 1.0f); 58 | 59 | VertexBuffer[n * 4u] .Position = mul(topLeft, Model); 60 | VertexBuffer[n * 4u + 1].Position = mul(topRight, Model); 61 | VertexBuffer[n * 4u + 2].Position = mul(bottomLeft, Model); 62 | VertexBuffer[n * 4u + 3].Position = mul(bottomRight, Model); 63 | 64 | VertexBuffer[n * 4u] .Texcoord = float2(sprite.TexU, sprite.TexV); 65 | VertexBuffer[n * 4u + 1].Texcoord = float2(sprite.TexU + sprite.TexW, sprite.TexV); 66 | VertexBuffer[n * 4u + 2].Texcoord = float2(sprite.TexU, sprite.TexV + sprite.TexH); 67 | VertexBuffer[n * 4u + 3].Texcoord = float2(sprite.TexU + sprite.TexW, sprite.TexV + sprite.TexH); 68 | 69 | VertexBuffer[n * 4u] .Color = sprite.Color; 70 | VertexBuffer[n * 4u + 1].Color = sprite.Color; 71 | VertexBuffer[n * 4u + 2].Color = sprite.Color; 72 | VertexBuffer[n * 4u + 3].Color = sprite.Color; 73 | } 74 | -------------------------------------------------------------------------------- /Examples/ClearScreenMultiWindow.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_Window* SecondWindow = NULL; 4 | 5 | static int Init(Context* context) 6 | { 7 | int result = CommonInit(context, 0); 8 | if (result < 0) 9 | { 10 | return result; 11 | } 12 | 13 | SecondWindow = SDL_CreateWindow("ClearScreenMultiWindow (2)", 640, 480, 0); 14 | if (SecondWindow == NULL) 15 | { 16 | SDL_Log("CreateWindow failed: %s", SDL_GetError()); 17 | return -1; 18 | } 19 | 20 | if (!SDL_ClaimWindowForGPUDevice(context->Device, SecondWindow)) 21 | { 22 | SDL_Log("GPUClaimWindow failed"); 23 | return -1; 24 | } 25 | 26 | return 0; 27 | } 28 | 29 | static int Update(Context* context) 30 | { 31 | return 0; 32 | } 33 | 34 | static int Draw(Context* context) 35 | { 36 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 37 | if (cmdbuf == NULL) 38 | { 39 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 40 | return -1; 41 | } 42 | 43 | SDL_GPUTexture* swapchainTexture; 44 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 45 | SDL_Log("AcquireGpuSwapchainTexture failed: %s", SDL_GetError()); 46 | return -1; 47 | } 48 | 49 | if (swapchainTexture != NULL) 50 | { 51 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 52 | colorTargetInfo.texture = swapchainTexture; 53 | colorTargetInfo.clear_color = (SDL_FColor){ 0.3f, 0.4f, 0.5f, 1.0f }; 54 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 55 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 56 | 57 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 58 | SDL_EndGPURenderPass(renderPass); 59 | } 60 | 61 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, SecondWindow, &swapchainTexture, NULL, NULL)) { 62 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 63 | return -1; 64 | } 65 | 66 | if (swapchainTexture != NULL) 67 | { 68 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 69 | colorTargetInfo.texture = swapchainTexture; 70 | colorTargetInfo.clear_color = (SDL_FColor){ 1.0f, 0.5f, 0.6f, 1.0f }; 71 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 72 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 73 | 74 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 75 | SDL_EndGPURenderPass(renderPass); 76 | } 77 | 78 | SDL_SubmitGPUCommandBuffer(cmdbuf); 79 | 80 | return 0; 81 | } 82 | 83 | static void Quit(Context* context) 84 | { 85 | SDL_ReleaseWindowFromGPUDevice(context->Device, SecondWindow); 86 | SDL_DestroyWindow(SecondWindow); 87 | SecondWindow = NULL; 88 | 89 | CommonQuit(context); 90 | } 91 | 92 | Example ClearScreenMultiWindow_Example = { "ClearScreenMultiWindow", Init, Update, Draw, Quit }; 93 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/SpriteBatch.comp.msl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace metal; 5 | 6 | struct SpriteComputeData 7 | { 8 | packed_float3 Position; 9 | float Rotation; 10 | float2 Scale; 11 | float2 Padding; 12 | float TexU; 13 | float TexV; 14 | float TexW; 15 | float TexH; 16 | float4 Color; 17 | }; 18 | 19 | struct type_StructuredBuffer_SpriteComputeData 20 | { 21 | SpriteComputeData _m0[1]; 22 | }; 23 | 24 | struct SpriteVertex 25 | { 26 | float4 Position; 27 | float2 Texcoord; 28 | float4 Color; 29 | }; 30 | 31 | struct type_RWStructuredBuffer_SpriteVertex 32 | { 33 | SpriteVertex _m0[1]; 34 | }; 35 | 36 | kernel void main0(const device type_StructuredBuffer_SpriteComputeData& ComputeBuffer [[buffer(0)]], device type_RWStructuredBuffer_SpriteVertex& VertexBuffer [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) 37 | { 38 | float3 _55 = float3(ComputeBuffer._m0[gl_GlobalInvocationID.x].Position); 39 | float _57 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Rotation; 40 | float2 _59 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Scale; 41 | float _61 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexU; 42 | float _63 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexV; 43 | float _65 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexW; 44 | float _67 = ComputeBuffer._m0[gl_GlobalInvocationID.x].TexH; 45 | float4 _69 = ComputeBuffer._m0[gl_GlobalInvocationID.x].Color; 46 | float _75 = cos(_57); 47 | float _76 = sin(_57); 48 | float4x4 _87 = (float4x4(float4(1.0, 0.0, 0.0, 0.0), float4(0.0, 1.0, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(_55, 1.0)) * float4x4(float4(_75, _76, 0.0, 0.0), float4(-_76, _75, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0))) * float4x4(float4(_59.x, 0.0, 0.0, 0.0), float4(0.0, _59.y, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0)); 49 | uint _89 = gl_GlobalInvocationID.x * 4u; 50 | VertexBuffer._m0[_89].Position = _87 * float4(0.0, 0.0, 0.0, 1.0); 51 | uint _92 = _89 + 1u; 52 | VertexBuffer._m0[_92].Position = _87 * float4(1.0, 0.0, 0.0, 1.0); 53 | uint _95 = _89 + 2u; 54 | VertexBuffer._m0[_95].Position = _87 * float4(0.0, 1.0, 0.0, 1.0); 55 | uint _98 = _89 + 3u; 56 | VertexBuffer._m0[_98].Position = _87 * float4(1.0, 1.0, 0.0, 1.0); 57 | VertexBuffer._m0[_89].Texcoord = float2(_61, _63); 58 | float _102 = _61 + _65; 59 | VertexBuffer._m0[_92].Texcoord = float2(_102, _63); 60 | float _105 = _63 + _67; 61 | VertexBuffer._m0[_95].Texcoord = float2(_61, _105); 62 | VertexBuffer._m0[_98].Texcoord = float2(_102, _105); 63 | VertexBuffer._m0[_89].Color = _69; 64 | VertexBuffer._m0[_92].Color = _69; 65 | VertexBuffer._m0[_95].Color = _69; 66 | VertexBuffer._m0[_98].Color = _69; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Content/Shaders/Compiled/MSL/PullSpriteBatch.vert.msl: -------------------------------------------------------------------------------- 1 | #pragma clang diagnostic ignored "-Wmissing-prototypes" 2 | #pragma clang diagnostic ignored "-Wmissing-braces" 3 | 4 | #include 5 | #include 6 | 7 | using namespace metal; 8 | 9 | template 10 | struct spvUnsafeArray 11 | { 12 | T elements[Num ? Num : 1]; 13 | 14 | thread T& operator [] (size_t pos) thread 15 | { 16 | return elements[pos]; 17 | } 18 | constexpr const thread T& operator [] (size_t pos) const thread 19 | { 20 | return elements[pos]; 21 | } 22 | 23 | device T& operator [] (size_t pos) device 24 | { 25 | return elements[pos]; 26 | } 27 | constexpr const device T& operator [] (size_t pos) const device 28 | { 29 | return elements[pos]; 30 | } 31 | 32 | constexpr const constant T& operator [] (size_t pos) const constant 33 | { 34 | return elements[pos]; 35 | } 36 | 37 | threadgroup T& operator [] (size_t pos) threadgroup 38 | { 39 | return elements[pos]; 40 | } 41 | constexpr const threadgroup T& operator [] (size_t pos) const threadgroup 42 | { 43 | return elements[pos]; 44 | } 45 | }; 46 | 47 | struct SpriteData 48 | { 49 | packed_float3 Position; 50 | float Rotation; 51 | float2 Scale; 52 | float2 Padding; 53 | float TexU; 54 | float TexV; 55 | float TexW; 56 | float TexH; 57 | float4 Color; 58 | }; 59 | 60 | struct type_StructuredBuffer_SpriteData 61 | { 62 | SpriteData _m0[1]; 63 | }; 64 | 65 | struct type_UniformBlock 66 | { 67 | float4x4 ViewProjectionMatrix; 68 | }; 69 | 70 | constant spvUnsafeArray _46 = spvUnsafeArray({ 0u, 1u, 2u, 3u, 2u, 1u }); 71 | constant spvUnsafeArray _51 = spvUnsafeArray({ float2(0.0), float2(1.0, 0.0), float2(0.0, 1.0), float2(1.0) }); 72 | 73 | struct main0_out 74 | { 75 | float2 out_var_TEXCOORD0 [[user(locn0)]]; 76 | float4 out_var_TEXCOORD1 [[user(locn1)]]; 77 | float4 gl_Position [[position]]; 78 | }; 79 | 80 | vertex main0_out main0(constant type_UniformBlock& UniformBlock [[buffer(0)]], const device type_StructuredBuffer_SpriteData& DataBuffer [[buffer(1)]], uint gl_VertexIndex [[vertex_id]]) 81 | { 82 | main0_out out = {}; 83 | uint _62 = gl_VertexIndex / 6u; 84 | uint _63 = gl_VertexIndex % 6u; 85 | float _82 = DataBuffer._m0[_62].TexU + DataBuffer._m0[_62].TexW; 86 | float _83 = DataBuffer._m0[_62].TexV + DataBuffer._m0[_62].TexH; 87 | spvUnsafeArray _88 = spvUnsafeArray({ float2(DataBuffer._m0[_62].TexU, DataBuffer._m0[_62].TexV), float2(_82, DataBuffer._m0[_62].TexV), float2(DataBuffer._m0[_62].TexU, _83), float2(_82, _83) }); 88 | spvUnsafeArray _60 = _88; 89 | float _89 = cos(DataBuffer._m0[_62].Rotation); 90 | float _90 = sin(DataBuffer._m0[_62].Rotation); 91 | out.out_var_TEXCOORD0 = _60[_46[_63]]; 92 | out.out_var_TEXCOORD1 = DataBuffer._m0[_62].Color; 93 | out.gl_Position = UniformBlock.ViewProjectionMatrix * float4((float2x2(float2(_89, _90), float2(-_90, _89)) * (_51[_46[_63]] * DataBuffer._m0[_62].Scale)) + float2(DataBuffer._m0[_62].Position[0], DataBuffer._m0[_62].Position[1]), DataBuffer._m0[_62].Position[2], 1.0); 94 | return out; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Examples/ComputeUniforms.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUComputePipeline* GradientPipeline; 4 | static SDL_GPUTexture* GradientRenderTexture; 5 | 6 | typedef struct GradientUniforms 7 | { 8 | float time; 9 | } GradientUniforms; 10 | 11 | static GradientUniforms GradientUniformValues; 12 | 13 | static int Init(Context* context) 14 | { 15 | int result = CommonInit(context, 0); 16 | if (result < 0) 17 | { 18 | return result; 19 | } 20 | 21 | GradientPipeline = CreateComputePipelineFromShader( 22 | context->Device, 23 | "GradientTexture.comp", 24 | &(SDL_GPUComputePipelineCreateInfo) { 25 | .num_readwrite_storage_textures = 1, 26 | .num_uniform_buffers = 1, 27 | .threadcount_x = 8, 28 | .threadcount_y = 8, 29 | .threadcount_z = 1, 30 | } 31 | ); 32 | 33 | int w, h; 34 | SDL_GetWindowSizeInPixels(context->Window, &w, &h); 35 | 36 | GradientRenderTexture = SDL_CreateGPUTexture(context->Device, &(SDL_GPUTextureCreateInfo){ 37 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 38 | .type = SDL_GPU_TEXTURETYPE_2D, 39 | .width = w, 40 | .height = h, 41 | .layer_count_or_depth = 1, 42 | .num_levels = 1, 43 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE 44 | }); 45 | 46 | GradientUniformValues.time = 0; 47 | 48 | return 0; 49 | } 50 | 51 | static int Update(Context* context) 52 | { 53 | GradientUniformValues.time += 0.01f; 54 | 55 | return 0; 56 | } 57 | 58 | static int Draw(Context* context) 59 | { 60 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 61 | if (cmdbuf == NULL) 62 | { 63 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 64 | return -1; 65 | } 66 | 67 | SDL_GPUTexture* swapchainTexture; 68 | Uint32 w, h; 69 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 70 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 71 | return -1; 72 | } 73 | 74 | if (swapchainTexture != NULL) 75 | { 76 | SDL_GPUComputePass* computePass = SDL_BeginGPUComputePass( 77 | cmdbuf, 78 | (SDL_GPUStorageTextureReadWriteBinding[]){{ 79 | .texture = GradientRenderTexture, 80 | .cycle = true 81 | }}, 82 | 1, 83 | NULL, 84 | 0 85 | ); 86 | 87 | SDL_BindGPUComputePipeline(computePass, GradientPipeline); 88 | SDL_PushGPUComputeUniformData(cmdbuf, 0, &GradientUniformValues, sizeof(GradientUniforms)); 89 | SDL_DispatchGPUCompute(computePass, w / 8 , h / 8 , 1); 90 | 91 | SDL_EndGPUComputePass(computePass); 92 | 93 | SDL_BlitGPUTexture( 94 | cmdbuf, 95 | &(SDL_GPUBlitInfo){ 96 | .source.texture = GradientRenderTexture, 97 | .source.w = w, 98 | .source.h = h, 99 | .destination.texture = swapchainTexture, 100 | .destination.w = w, 101 | .destination.h = h, 102 | .load_op = SDL_GPU_LOADOP_DONT_CARE, 103 | .filter = SDL_GPU_FILTER_LINEAR 104 | } 105 | ); 106 | } 107 | 108 | SDL_SubmitGPUCommandBuffer(cmdbuf); 109 | 110 | return 0; 111 | } 112 | 113 | static void Quit(Context* context) 114 | { 115 | SDL_ReleaseGPUComputePipeline(context->Device, GradientPipeline); 116 | SDL_ReleaseGPUTexture(context->Device, GradientRenderTexture); 117 | 118 | CommonQuit(context); 119 | } 120 | 121 | Example ComputeUniforms_Example = { "ComputeUniforms", Init, Update, Draw, Quit }; 122 | -------------------------------------------------------------------------------- /Examples/GenerateMipmaps.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUTexture *MipmapTexture; 4 | 5 | static int Init(Context* context) 6 | { 7 | int result = CommonInit(context, 0); 8 | if (result < 0) 9 | { 10 | return result; 11 | } 12 | 13 | MipmapTexture = SDL_CreateGPUTexture( 14 | context->Device, 15 | &(SDL_GPUTextureCreateInfo){ 16 | .type = SDL_GPU_TEXTURETYPE_2D, 17 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 18 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, 19 | .width = 32, 20 | .height = 32, 21 | .layer_count_or_depth = 1, 22 | .num_levels = 3 23 | } 24 | ); 25 | 26 | Uint32 byteCount = 32 * 32 * 4; 27 | SDL_GPUTransferBuffer *textureTransferBuffer = SDL_CreateGPUTransferBuffer( 28 | context->Device, 29 | &(SDL_GPUTransferBufferCreateInfo) { 30 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 31 | .size = byteCount 32 | } 33 | ); 34 | Uint8* textureTransferData = SDL_MapGPUTransferBuffer( 35 | context->Device, 36 | textureTransferBuffer, 37 | false 38 | ); 39 | 40 | SDL_Surface* imageData = LoadImage("cube0.bmp", 4); 41 | if (imageData == NULL) 42 | { 43 | SDL_Log("Could not load image data!"); 44 | return -1; 45 | } 46 | SDL_memcpy(textureTransferData, imageData->pixels, byteCount); 47 | SDL_DestroySurface(imageData); 48 | 49 | SDL_UnmapGPUTransferBuffer(context->Device, textureTransferBuffer); 50 | 51 | SDL_GPUCommandBuffer *cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 52 | SDL_GPUCopyPass *copyPass = SDL_BeginGPUCopyPass(cmdbuf); 53 | SDL_UploadToGPUTexture( 54 | copyPass, 55 | &(SDL_GPUTextureTransferInfo){ 56 | .transfer_buffer = textureTransferBuffer 57 | }, 58 | &(SDL_GPUTextureRegion) { 59 | .texture = MipmapTexture, 60 | .w = 32, 61 | .h = 32, 62 | .d = 1 63 | }, 64 | false 65 | ); 66 | SDL_EndGPUCopyPass(copyPass); 67 | SDL_GenerateMipmapsForGPUTexture(cmdbuf, MipmapTexture); 68 | 69 | SDL_SubmitGPUCommandBuffer(cmdbuf); 70 | 71 | SDL_ReleaseGPUTransferBuffer(context->Device, textureTransferBuffer); 72 | 73 | return 0; 74 | } 75 | 76 | static int Update(Context* context) 77 | { 78 | return 0; 79 | } 80 | 81 | static int Draw(Context* context) 82 | { 83 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 84 | if (cmdbuf == NULL) 85 | { 86 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 87 | return -1; 88 | } 89 | 90 | SDL_GPUTexture* swapchainTexture; 91 | Uint32 w, h; 92 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 93 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 94 | return -1; 95 | } 96 | 97 | if (swapchainTexture != NULL) 98 | { 99 | /* Blit the smallest mip level */ 100 | SDL_BlitGPUTexture( 101 | cmdbuf, 102 | &(SDL_GPUBlitInfo){ 103 | .source.texture = MipmapTexture, 104 | .source.w = 8, 105 | .source.h = 8, 106 | .source.mip_level = 2, 107 | .destination.texture = swapchainTexture, 108 | .destination.w = w, 109 | .destination.h = h, 110 | .load_op = SDL_GPU_LOADOP_DONT_CARE 111 | } 112 | ); 113 | } 114 | 115 | SDL_SubmitGPUCommandBuffer(cmdbuf); 116 | 117 | return 0; 118 | } 119 | 120 | static void Quit(Context* context) 121 | { 122 | SDL_ReleaseGPUTexture(context->Device, MipmapTexture); 123 | CommonQuit(context); 124 | } 125 | 126 | Example GenerateMipmaps_Example = { "GenerateMipmaps", Init, Update, Draw, Quit }; 127 | -------------------------------------------------------------------------------- /Examples/Common.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL_GPU_EXAMPLES_H 2 | #define SDL_GPU_EXAMPLES_H 3 | 4 | #include 5 | 6 | typedef struct Context 7 | { 8 | const char* ExampleName; 9 | const char* BasePath; 10 | SDL_Window* Window; 11 | SDL_GPUDevice* Device; 12 | bool LeftPressed; 13 | bool RightPressed; 14 | bool DownPressed; 15 | bool UpPressed; 16 | float DeltaTime; 17 | } Context; 18 | 19 | int CommonInit(Context* context, SDL_WindowFlags windowFlags); 20 | void CommonQuit(Context* context); 21 | 22 | void InitializeAssetLoader(); 23 | SDL_Surface* LoadImage(const char* imageFilename, int desiredChannels); 24 | float* LoadHDRImage(const char* imageFilename, int* pWidth, int* pHeight, int* pChannels, int desiredChannels); 25 | void* LoadASTCImage(const char* imageFilename, int* pWidth, int* pHeight, int* pImageDataLength); 26 | void* LoadDDSImage(const char* imageFilename, SDL_GPUTextureFormat format, int* pWidth, int* pHeight, int* pImageDataLength); 27 | 28 | SDL_GPUShader* LoadShader( 29 | SDL_GPUDevice* device, 30 | const char* shaderFilename, 31 | Uint32 samplerCount, 32 | Uint32 uniformBufferCount, 33 | Uint32 storageBufferCount, 34 | Uint32 storageTextureCount 35 | ); 36 | SDL_GPUComputePipeline* CreateComputePipelineFromShader( 37 | SDL_GPUDevice* device, 38 | const char* shaderFilename, 39 | SDL_GPUComputePipelineCreateInfo* createInfo 40 | ); 41 | 42 | // Vertex Formats 43 | typedef struct PositionVertex 44 | { 45 | float x, y, z; 46 | } PositionVertex; 47 | 48 | typedef struct PositionColorVertex 49 | { 50 | float x, y, z; 51 | Uint8 r, g, b, a; 52 | } PositionColorVertex; 53 | 54 | typedef struct PositionTextureVertex 55 | { 56 | float x, y, z; 57 | float u, v; 58 | } PositionTextureVertex; 59 | 60 | // Matrix Math 61 | typedef struct Matrix4x4 62 | { 63 | float m11, m12, m13, m14; 64 | float m21, m22, m23, m24; 65 | float m31, m32, m33, m34; 66 | float m41, m42, m43, m44; 67 | } Matrix4x4; 68 | 69 | typedef struct Vector3 70 | { 71 | float x, y, z; 72 | } Vector3; 73 | 74 | Matrix4x4 Matrix4x4_Multiply(Matrix4x4 matrix1, Matrix4x4 matrix2); 75 | Matrix4x4 Matrix4x4_CreateRotationZ(float radians); 76 | Matrix4x4 Matrix4x4_CreateTranslation(float x, float y, float z); 77 | Matrix4x4 Matrix4x4_CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNearPlane, float zFarPlane); 78 | Matrix4x4 Matrix4x4_CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance); 79 | Matrix4x4 Matrix4x4_CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector); 80 | Vector3 Vector3_Normalize(Vector3 vec); 81 | float Vector3_Dot(Vector3 vecA, Vector3 vecB); 82 | Vector3 Vector3_Cross(Vector3 vecA, Vector3 vecB); 83 | 84 | // Examples 85 | typedef struct Example 86 | { 87 | const char* Name; 88 | int (*Init)(Context* context); 89 | int (*Update)(Context* context); 90 | int (*Draw)(Context* context); 91 | void (*Quit)(Context* context); 92 | } Example; 93 | 94 | extern Example ClearScreen_Example; 95 | extern Example ClearScreenMultiWindow_Example; 96 | extern Example BasicTriangle_Example; 97 | extern Example BasicVertexBuffer_Example; 98 | extern Example CullMode_Example; 99 | extern Example BasicStencil_Example; 100 | extern Example InstancedIndexed_Example; 101 | extern Example TexturedQuad_Example; 102 | extern Example TexturedAnimatedQuad_Example; 103 | extern Example Clear3DSlice_Example; 104 | extern Example BasicCompute_Example; 105 | extern Example ComputeUniforms_Example; 106 | extern Example ToneMapping_Example; 107 | extern Example CustomSampling_Example; 108 | extern Example DrawIndirect_Example; 109 | extern Example ComputeSampler_Example; 110 | extern Example ComputeSpriteBatch_Example; 111 | extern Example CopyAndReadback_Example; 112 | extern Example CopyConsistency_Example; 113 | extern Example Texture2DArray_Example; 114 | extern Example TriangleMSAA_Example; 115 | extern Example Cubemap_Example; 116 | extern Example WindowResize_Example; 117 | extern Example Blit2DArray_Example; 118 | extern Example BlitCube_Example; 119 | extern Example BlitMirror_Example; 120 | extern Example GenerateMipmaps_Example; 121 | extern Example Latency_Example; 122 | extern Example DepthSampler_Example; 123 | extern Example PullSpriteBatch_Example; 124 | extern Example TextureTypeTest_Example; 125 | extern Example CompressedTextures_Example; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /Examples/WindowResize.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | typedef struct Resolution 4 | { 5 | Uint32 x, y; 6 | } Resolution; 7 | 8 | static const Resolution Resolutions[] = 9 | { 10 | { 640, 480 }, 11 | { 1280, 720 }, 12 | { 1024, 1024 }, 13 | { 1600, 900 }, 14 | { 1920, 1080 }, 15 | { 3200, 1800 }, 16 | { 3840, 2160 } 17 | }; 18 | static Uint32 ResolutionCount = SDL_arraysize(Resolutions); 19 | 20 | static SDL_GPUGraphicsPipeline* Pipeline; 21 | static Sint32 ResolutionIndex; 22 | 23 | static int Init(Context* context) 24 | { 25 | int result = CommonInit(context, 0); 26 | if (result < 0) 27 | { 28 | return result; 29 | } 30 | 31 | ResolutionIndex = 0; 32 | 33 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "RawTriangle.vert", 0, 0, 0, 0); 34 | if (vertexShader == NULL) 35 | { 36 | SDL_Log("Failed to create vertex shader!"); 37 | return -1; 38 | } 39 | 40 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 41 | if (fragmentShader == NULL) 42 | { 43 | SDL_Log("Failed to create fragment shader!"); 44 | return -1; 45 | } 46 | 47 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 48 | .target_info = { 49 | .num_color_targets = 1, 50 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 51 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 52 | }}, 53 | }, 54 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 55 | .vertex_shader = vertexShader, 56 | .fragment_shader = fragmentShader, 57 | .rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL 58 | }; 59 | 60 | Pipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 61 | if (Pipeline == NULL) 62 | { 63 | SDL_Log("Failed to create pipeline!"); 64 | return -1; 65 | } 66 | 67 | SDL_ReleaseGPUShader(context->Device, vertexShader); 68 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 69 | 70 | SDL_Log("Press Left and Right to resize the window!"); 71 | 72 | return 0; 73 | } 74 | 75 | static int Update(Context* context) 76 | { 77 | bool changeResolution = false; 78 | 79 | if (context->RightPressed) 80 | { 81 | ResolutionIndex = (ResolutionIndex + 1) % ResolutionCount; 82 | changeResolution = true; 83 | } 84 | 85 | if (context->LeftPressed) 86 | { 87 | ResolutionIndex -= 1; 88 | if (ResolutionIndex < 0) 89 | { 90 | ResolutionIndex = ResolutionCount - 1; 91 | } 92 | changeResolution = true; 93 | } 94 | 95 | if (changeResolution) 96 | { 97 | Resolution currentResolution = Resolutions[ResolutionIndex]; 98 | SDL_Log("Setting resolution to: %u, %u", currentResolution.x, currentResolution.y); 99 | SDL_SetWindowSize(context->Window, currentResolution.x, currentResolution.y); 100 | SDL_SetWindowPosition(context->Window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); 101 | SDL_SyncWindow(context->Window); 102 | } 103 | 104 | return 0; 105 | } 106 | 107 | static int Draw(Context* context) 108 | { 109 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 110 | if (cmdbuf == NULL) 111 | { 112 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 113 | return -1; 114 | } 115 | 116 | SDL_GPUTexture* swapchainTexture; 117 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 118 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 119 | return -1; 120 | } 121 | 122 | if (swapchainTexture != NULL) 123 | { 124 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 125 | colorTargetInfo.texture = swapchainTexture; 126 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 127 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 128 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 129 | 130 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 131 | SDL_BindGPUGraphicsPipeline(renderPass, Pipeline); 132 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 133 | SDL_EndGPURenderPass(renderPass); 134 | } 135 | 136 | SDL_SubmitGPUCommandBuffer(cmdbuf); 137 | 138 | return 0; 139 | } 140 | 141 | static void Quit(Context* context) 142 | { 143 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipeline); 144 | CommonQuit(context); 145 | } 146 | 147 | Example WindowResize_Example = { "WindowResize", Init, Update, Draw, Quit }; 148 | -------------------------------------------------------------------------------- /Examples/BasicTriangle.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* FillPipeline; 4 | static SDL_GPUGraphicsPipeline* LinePipeline; 5 | static SDL_GPUViewport SmallViewport = { 160, 120, 320, 240, 0.1f, 1.0f }; 6 | static SDL_Rect ScissorRect = { 320, 240, 320, 240 }; 7 | 8 | static bool UseWireframeMode = false; 9 | static bool UseSmallViewport = false; 10 | static bool UseScissorRect = false; 11 | 12 | static int Init(Context* context) 13 | { 14 | int result = CommonInit(context, 0); 15 | if (result < 0) 16 | { 17 | return result; 18 | } 19 | 20 | // Create the shaders 21 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "RawTriangle.vert", 0, 0, 0, 0); 22 | if (vertexShader == NULL) 23 | { 24 | SDL_Log("Failed to create vertex shader!"); 25 | return -1; 26 | } 27 | 28 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 29 | if (fragmentShader == NULL) 30 | { 31 | SDL_Log("Failed to create fragment shader!"); 32 | return -1; 33 | } 34 | 35 | // Create the pipelines 36 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 37 | .target_info = { 38 | .num_color_targets = 1, 39 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 40 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 41 | }}, 42 | }, 43 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 44 | .vertex_shader = vertexShader, 45 | .fragment_shader = fragmentShader, 46 | }; 47 | 48 | pipelineCreateInfo.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL; 49 | FillPipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 50 | if (FillPipeline == NULL) 51 | { 52 | SDL_Log("Failed to create fill pipeline!"); 53 | return -1; 54 | } 55 | 56 | pipelineCreateInfo.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_LINE; 57 | LinePipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 58 | if (LinePipeline == NULL) 59 | { 60 | SDL_Log("Failed to create line pipeline!"); 61 | return -1; 62 | } 63 | 64 | // Clean up shader resources 65 | SDL_ReleaseGPUShader(context->Device, vertexShader); 66 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 67 | 68 | // Finally, print instructions! 69 | SDL_Log("Press Left to toggle wireframe mode"); 70 | SDL_Log("Press Down to toggle small viewport"); 71 | SDL_Log("Press Right to toggle scissor rect"); 72 | 73 | return 0; 74 | } 75 | 76 | static int Update(Context* context) 77 | { 78 | if (context->LeftPressed) 79 | { 80 | UseWireframeMode = !UseWireframeMode; 81 | } 82 | 83 | if (context->DownPressed) 84 | { 85 | UseSmallViewport = !UseSmallViewport; 86 | } 87 | 88 | if (context->RightPressed) 89 | { 90 | UseScissorRect = !UseScissorRect; 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | static int Draw(Context* context) 97 | { 98 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 99 | if (cmdbuf == NULL) 100 | { 101 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 102 | return -1; 103 | } 104 | 105 | SDL_GPUTexture* swapchainTexture; 106 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 107 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 108 | return -1; 109 | } 110 | 111 | if (swapchainTexture != NULL) 112 | { 113 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 114 | colorTargetInfo.texture = swapchainTexture; 115 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 116 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 117 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 118 | 119 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 120 | SDL_BindGPUGraphicsPipeline(renderPass, UseWireframeMode ? LinePipeline : FillPipeline); 121 | if (UseSmallViewport) 122 | { 123 | SDL_SetGPUViewport(renderPass, &SmallViewport); 124 | } 125 | if (UseScissorRect) 126 | { 127 | SDL_SetGPUScissor(renderPass, &ScissorRect); 128 | } 129 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 130 | SDL_EndGPURenderPass(renderPass); 131 | } 132 | 133 | SDL_SubmitGPUCommandBuffer(cmdbuf); 134 | 135 | return 0; 136 | } 137 | 138 | static void Quit(Context* context) 139 | { 140 | SDL_ReleaseGPUGraphicsPipeline(context->Device, FillPipeline); 141 | SDL_ReleaseGPUGraphicsPipeline(context->Device, LinePipeline); 142 | 143 | UseWireframeMode = false; 144 | UseSmallViewport = false; 145 | UseScissorRect = false; 146 | 147 | CommonQuit(context); 148 | } 149 | 150 | Example BasicTriangle_Example = { "BasicTriangle", Init, Update, Draw, Quit }; 151 | -------------------------------------------------------------------------------- /Examples/Clear3DSlice.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUTexture *Texture3D; 4 | 5 | static int Init(Context* context) 6 | { 7 | int result = CommonInit(context, SDL_WINDOW_RESIZABLE); 8 | if (result < 0) 9 | { 10 | return result; 11 | } 12 | 13 | SDL_GPUTextureFormat swapchainFormat = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window); 14 | 15 | Texture3D = SDL_CreateGPUTexture( 16 | context->Device, 17 | &(SDL_GPUTextureCreateInfo){ 18 | .type = SDL_GPU_TEXTURETYPE_3D, 19 | .format = swapchainFormat, 20 | .width = 64, 21 | .height = 64, 22 | .layer_count_or_depth = 4, 23 | .num_levels = 1, 24 | .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER 25 | } 26 | ); 27 | 28 | return 0; 29 | } 30 | 31 | static int Update(Context* context) 32 | { 33 | return 0; 34 | } 35 | 36 | static int Draw(Context* context) 37 | { 38 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 39 | if (cmdbuf == NULL) 40 | { 41 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 42 | return -1; 43 | } 44 | 45 | SDL_GPUTexture* swapchainTexture; 46 | Uint32 w, h; 47 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 48 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 49 | return -1; 50 | } 51 | 52 | if (swapchainTexture != NULL) 53 | { 54 | SDL_GPURenderPass *renderPass = SDL_BeginGPURenderPass( 55 | cmdbuf, 56 | &(SDL_GPUColorTargetInfo){ 57 | .texture = Texture3D, 58 | .cycle = true, 59 | .load_op = SDL_GPU_LOADOP_CLEAR, 60 | .store_op = SDL_GPU_STOREOP_STORE, 61 | .clear_color = { 1.0f, 0.0f, 0.0f, 1.0f }, 62 | .layer_or_depth_plane = 0 63 | }, 64 | 1, 65 | NULL 66 | ); 67 | SDL_EndGPURenderPass(renderPass); 68 | 69 | renderPass = SDL_BeginGPURenderPass( 70 | cmdbuf, 71 | &(SDL_GPUColorTargetInfo){ 72 | .texture = Texture3D, 73 | .cycle = false, 74 | .load_op = SDL_GPU_LOADOP_CLEAR, 75 | .store_op = SDL_GPU_STOREOP_STORE, 76 | .clear_color = { 0.0f, 1.0f, 0.0f, 1.0f }, 77 | .layer_or_depth_plane = 1 78 | }, 79 | 1, 80 | NULL 81 | ); 82 | SDL_EndGPURenderPass(renderPass); 83 | 84 | renderPass = SDL_BeginGPURenderPass( 85 | cmdbuf, 86 | &(SDL_GPUColorTargetInfo){ 87 | .texture = Texture3D, 88 | .cycle = false, 89 | .load_op = SDL_GPU_LOADOP_CLEAR, 90 | .store_op = SDL_GPU_STOREOP_STORE, 91 | .clear_color = { 0.0f, 0.0f, 1.0f, 1.0f }, 92 | .layer_or_depth_plane = 2 93 | }, 94 | 1, 95 | NULL 96 | ); 97 | SDL_EndGPURenderPass(renderPass); 98 | 99 | renderPass = SDL_BeginGPURenderPass( 100 | cmdbuf, 101 | &(SDL_GPUColorTargetInfo){ 102 | .texture = Texture3D, 103 | .cycle = false, 104 | .load_op = SDL_GPU_LOADOP_CLEAR, 105 | .store_op = SDL_GPU_STOREOP_STORE, 106 | .clear_color = { 1.0f, 0.0f, 1.0f, 1.0f }, 107 | .layer_or_depth_plane = 3 108 | }, 109 | 1, 110 | NULL 111 | ); 112 | SDL_EndGPURenderPass(renderPass); 113 | 114 | for (int i = 0; i < 4; i += 1) { 115 | Uint32 destX = (i % 2) * (w / 2); 116 | Uint32 destY = (i > 1) ? (h / 2) : 0; 117 | SDL_BlitGPUTexture( 118 | cmdbuf, 119 | &(SDL_GPUBlitInfo){ 120 | .source.texture = Texture3D, 121 | .source.layer_or_depth_plane = i, 122 | .source.w = 64, 123 | .source.h = 64, 124 | .destination.texture = swapchainTexture, 125 | .destination.x = destX, 126 | .destination.y = destY, 127 | .destination.w = w / 2, 128 | .destination.h = h / 2, 129 | .load_op = SDL_GPU_LOADOP_LOAD, 130 | .filter = SDL_GPU_FILTER_NEAREST 131 | } 132 | ); 133 | } 134 | } 135 | 136 | SDL_SubmitGPUCommandBuffer(cmdbuf); 137 | 138 | return 0; 139 | } 140 | 141 | static void Quit(Context* context) 142 | { 143 | SDL_ReleaseGPUTexture(context->Device, Texture3D); 144 | CommonQuit(context); 145 | } 146 | 147 | Example Clear3DSlice_Example = { "Clear3DSlice", Init, Update, Draw, Quit }; 148 | -------------------------------------------------------------------------------- /Examples/BlitMirror.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUTexture* Texture; 4 | 5 | static Uint32 TextureWidth, TextureHeight; 6 | 7 | static int Init(Context* context) 8 | { 9 | int result = CommonInit(context, 0); 10 | if (result < 0) 11 | { 12 | return result; 13 | } 14 | 15 | // Load the image 16 | SDL_Surface *imageData = LoadImage("ravioli.bmp", 4); 17 | if (imageData == NULL) 18 | { 19 | SDL_Log("Could not load image data!"); 20 | return -1; 21 | } 22 | 23 | TextureWidth = imageData->w; 24 | TextureHeight = imageData->h; 25 | 26 | // Create texture resource 27 | Texture = SDL_CreateGPUTexture( 28 | context->Device, 29 | &(SDL_GPUTextureCreateInfo){ 30 | .type = SDL_GPU_TEXTURETYPE_2D, 31 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 32 | .width = imageData->w, 33 | .height = imageData->h, 34 | .layer_count_or_depth = 1, 35 | .num_levels = 1, 36 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER 37 | } 38 | ); 39 | 40 | SDL_GPUTransferBuffer* uploadTransferBuffer = SDL_CreateGPUTransferBuffer( 41 | context->Device, 42 | &(SDL_GPUTransferBufferCreateInfo) { 43 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 44 | .size = imageData->w * imageData->h * 4 45 | } 46 | ); 47 | 48 | Uint8* uploadTransferPtr = SDL_MapGPUTransferBuffer( 49 | context->Device, 50 | uploadTransferBuffer, 51 | false 52 | ); 53 | SDL_memcpy(uploadTransferPtr, imageData->pixels, imageData->w * imageData->h * 4); 54 | SDL_UnmapGPUTransferBuffer(context->Device, uploadTransferBuffer); 55 | 56 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 57 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf); 58 | SDL_UploadToGPUTexture( 59 | copyPass, 60 | &(SDL_GPUTextureTransferInfo) { 61 | .transfer_buffer = uploadTransferBuffer, 62 | }, 63 | &(SDL_GPUTextureRegion){ 64 | .texture = Texture, 65 | .w = TextureWidth, 66 | .h = TextureHeight, 67 | .d = 1 68 | }, 69 | false 70 | ); 71 | SDL_EndGPUCopyPass(copyPass); 72 | SDL_SubmitGPUCommandBuffer(cmdbuf); 73 | 74 | SDL_ReleaseGPUTransferBuffer(context->Device, uploadTransferBuffer); 75 | SDL_DestroySurface(imageData); 76 | 77 | return 0; 78 | } 79 | 80 | static int Update(Context* context) 81 | { 82 | return 0; 83 | } 84 | 85 | static int Draw(Context* context) 86 | { 87 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 88 | if (cmdbuf == NULL) 89 | { 90 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 91 | return -1; 92 | } 93 | 94 | SDL_GPUTexture* swapchainTexture; 95 | Uint32 w, h; 96 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 97 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 98 | return -1; 99 | } 100 | 101 | if (swapchainTexture != NULL) 102 | { 103 | SDL_GPURenderPass* clearPass = SDL_BeginGPURenderPass( 104 | cmdbuf, 105 | (SDL_GPUColorTargetInfo[]){{ 106 | .texture = swapchainTexture, 107 | .load_op = SDL_GPU_LOADOP_CLEAR, 108 | .store_op = SDL_GPU_STOREOP_STORE, 109 | .clear_color = { 0, 0, 0, 1 }, 110 | .cycle = false 111 | }}, 112 | 1, 113 | NULL 114 | ); 115 | SDL_EndGPURenderPass(clearPass); 116 | 117 | // Normal 118 | SDL_BlitGPUTexture( 119 | cmdbuf, 120 | &(SDL_GPUBlitInfo){ 121 | .source.texture = Texture, 122 | .source.w = TextureWidth, 123 | .source.h = TextureHeight, 124 | .destination.texture = swapchainTexture, 125 | .destination.w = w / 2, 126 | .destination.h = h / 2, 127 | .load_op = SDL_GPU_LOADOP_DONT_CARE, 128 | .filter = SDL_GPU_FILTER_NEAREST 129 | } 130 | ); 131 | 132 | // Flipped Horizontally 133 | SDL_BlitGPUTexture( 134 | cmdbuf, 135 | &(SDL_GPUBlitInfo){ 136 | .source.texture = Texture, 137 | .source.w = TextureWidth, 138 | .source.h = TextureHeight, 139 | .destination.texture = swapchainTexture, 140 | .destination.x = w / 2, 141 | .destination.w = w / 2, 142 | .destination.h = h / 2, 143 | .load_op = SDL_GPU_LOADOP_LOAD, 144 | .flip_mode = SDL_FLIP_HORIZONTAL, 145 | .filter = SDL_GPU_FILTER_NEAREST 146 | } 147 | ); 148 | 149 | // Flipped Vertically 150 | SDL_BlitGPUTexture( 151 | cmdbuf, 152 | &(SDL_GPUBlitInfo){ 153 | .source.texture = Texture, 154 | .source.w = TextureWidth, 155 | .source.h = TextureHeight, 156 | .destination.texture = swapchainTexture, 157 | .destination.w = w / 2, 158 | .destination.y = h / 2, 159 | .destination.h = h / 2, 160 | .load_op = SDL_GPU_LOADOP_LOAD, 161 | .flip_mode = SDL_FLIP_VERTICAL, 162 | .filter = SDL_GPU_FILTER_NEAREST 163 | } 164 | ); 165 | 166 | // Flipped Horizontally and Vertically 167 | SDL_BlitGPUTexture( 168 | cmdbuf, 169 | &(SDL_GPUBlitInfo){ 170 | .source.texture = Texture, 171 | .source.w = TextureWidth, 172 | .source.h = TextureHeight, 173 | .destination.texture = swapchainTexture, 174 | .destination.x = w / 2, 175 | .destination.w = w / 2, 176 | .destination.y = h / 2, 177 | .destination.h = h / 2, 178 | .load_op = SDL_GPU_LOADOP_LOAD, 179 | .flip_mode = SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL, 180 | .filter = SDL_GPU_FILTER_NEAREST 181 | } 182 | ); 183 | } 184 | 185 | SDL_SubmitGPUCommandBuffer(cmdbuf); 186 | 187 | return 0; 188 | } 189 | 190 | static void Quit(Context* context) 191 | { 192 | SDL_ReleaseGPUTexture(context->Device, Texture); 193 | 194 | CommonQuit(context); 195 | } 196 | 197 | Example BlitMirror_Example = { "BlitMirror", Init, Update, Draw, Quit }; 198 | -------------------------------------------------------------------------------- /Examples/BasicVertexBuffer.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* Pipeline; 4 | static SDL_GPUBuffer* VertexBuffer; 5 | 6 | static int Init(Context* context) 7 | { 8 | int result = CommonInit(context, 0); 9 | if (result < 0) 10 | { 11 | return result; 12 | } 13 | 14 | // Create the shaders 15 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "PositionColor.vert", 0, 0, 0, 0); 16 | if (vertexShader == NULL) 17 | { 18 | SDL_Log("Failed to create vertex shader!"); 19 | return -1; 20 | } 21 | 22 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 23 | if (fragmentShader == NULL) 24 | { 25 | SDL_Log("Failed to create fragment shader!"); 26 | return -1; 27 | } 28 | 29 | // Create the pipeline 30 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 31 | .target_info = { 32 | .num_color_targets = 1, 33 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 34 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window), 35 | }}, 36 | }, 37 | // This is set up to match the vertex shader layout! 38 | .vertex_input_state = (SDL_GPUVertexInputState){ 39 | .num_vertex_buffers = 1, 40 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 41 | .slot = 0, 42 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 43 | .instance_step_rate = 0, 44 | .pitch = sizeof(PositionColorVertex) 45 | }}, 46 | .num_vertex_attributes = 2, 47 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 48 | .buffer_slot = 0, 49 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 50 | .location = 0, 51 | .offset = 0 52 | }, { 53 | .buffer_slot = 0, 54 | .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, 55 | .location = 1, 56 | .offset = sizeof(float) * 3 57 | }} 58 | }, 59 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 60 | .vertex_shader = vertexShader, 61 | .fragment_shader = fragmentShader 62 | }; 63 | 64 | Pipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 65 | if (Pipeline == NULL) 66 | { 67 | SDL_Log("Failed to create pipeline!"); 68 | return -1; 69 | } 70 | 71 | SDL_ReleaseGPUShader(context->Device, vertexShader); 72 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 73 | 74 | // Create the vertex buffer 75 | VertexBuffer = SDL_CreateGPUBuffer( 76 | context->Device, 77 | &(SDL_GPUBufferCreateInfo) { 78 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 79 | .size = sizeof(PositionColorVertex) * 3 80 | } 81 | ); 82 | 83 | // To get data into the vertex buffer, we have to use a transfer buffer 84 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 85 | context->Device, 86 | &(SDL_GPUTransferBufferCreateInfo) { 87 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 88 | .size = sizeof(PositionColorVertex) * 3 89 | } 90 | ); 91 | 92 | PositionColorVertex* transferData = SDL_MapGPUTransferBuffer( 93 | context->Device, 94 | transferBuffer, 95 | false 96 | ); 97 | 98 | transferData[0] = (PositionColorVertex) { -1, -1, 0, 255, 0, 0, 255 }; 99 | transferData[1] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 100 | transferData[2] = (PositionColorVertex) { 0, 1, 0, 0, 0, 255, 255 }; 101 | 102 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 103 | 104 | // Upload the transfer data to the vertex buffer 105 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 106 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 107 | 108 | SDL_UploadToGPUBuffer( 109 | copyPass, 110 | &(SDL_GPUTransferBufferLocation) { 111 | .transfer_buffer = transferBuffer, 112 | .offset = 0 113 | }, 114 | &(SDL_GPUBufferRegion) { 115 | .buffer = VertexBuffer, 116 | .offset = 0, 117 | .size = sizeof(PositionColorVertex) * 3 118 | }, 119 | false 120 | ); 121 | 122 | SDL_EndGPUCopyPass(copyPass); 123 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 124 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 125 | 126 | return 0; 127 | } 128 | 129 | static int Update(Context* context) 130 | { 131 | return 0; 132 | } 133 | 134 | static int Draw(Context* context) 135 | { 136 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 137 | if (cmdbuf == NULL) 138 | { 139 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 140 | return -1; 141 | } 142 | 143 | SDL_GPUTexture* swapchainTexture; 144 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 145 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 146 | return -1; 147 | } 148 | 149 | if (swapchainTexture != NULL) 150 | { 151 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 152 | colorTargetInfo.texture = swapchainTexture; 153 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 154 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 155 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 156 | 157 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass( 158 | cmdbuf, 159 | &colorTargetInfo, 160 | 1, 161 | NULL 162 | ); 163 | 164 | SDL_BindGPUGraphicsPipeline(renderPass, Pipeline); 165 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBuffer, .offset = 0 }, 1); 166 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 167 | 168 | SDL_EndGPURenderPass(renderPass); 169 | } 170 | 171 | SDL_SubmitGPUCommandBuffer(cmdbuf); 172 | 173 | return 0; 174 | } 175 | 176 | static void Quit(Context* context) 177 | { 178 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipeline); 179 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 180 | 181 | CommonQuit(context); 182 | } 183 | 184 | Example BasicVertexBuffer_Example = { "BasicVertexBuffer", Init, Update, Draw, Quit }; 185 | -------------------------------------------------------------------------------- /Examples/TriangleMSAA.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* Pipelines[4]; 4 | static SDL_GPUTexture* MSAARenderTextures[4]; 5 | static SDL_GPUTexture* ResolveTexture; 6 | static int SampleCounts; 7 | 8 | static SDL_GPUTextureFormat RTFormat; 9 | 10 | static int CurrentSampleCount = 0; 11 | 12 | static int Init(Context* context) 13 | { 14 | int result = CommonInit(context, 0); 15 | if (result < 0) 16 | { 17 | return result; 18 | } 19 | 20 | // Create the shaders 21 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "RawTriangle.vert", 0, 0, 0, 0); 22 | if (vertexShader == NULL) 23 | { 24 | SDL_Log("Failed to create vertex shader!"); 25 | return -1; 26 | } 27 | 28 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 29 | if (fragmentShader == NULL) 30 | { 31 | SDL_Log("Failed to create fragment shader!"); 32 | return -1; 33 | } 34 | 35 | // Create the pipelines 36 | RTFormat = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window); 37 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 38 | .target_info = { 39 | .num_color_targets = 1, 40 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 41 | .format = RTFormat 42 | }}, 43 | }, 44 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 45 | .vertex_shader = vertexShader, 46 | .fragment_shader = fragmentShader, 47 | }; 48 | 49 | SampleCounts = 0; 50 | for (int i = 0; i < SDL_arraysize(Pipelines); i += 1) 51 | { 52 | SDL_GPUSampleCount sample_count = (SDL_GPUSampleCount) i; 53 | if (!SDL_GPUTextureSupportsSampleCount( 54 | context->Device, 55 | RTFormat, 56 | sample_count)) { 57 | SDL_Log("Sample count %d not supported", (1 << CurrentSampleCount)); 58 | continue; 59 | } 60 | pipelineCreateInfo.multisample_state.sample_count = sample_count; 61 | Pipelines[SampleCounts] = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 62 | if (Pipelines[SampleCounts] == NULL) 63 | { 64 | SDL_Log("Failed to create pipeline!"); 65 | return -1; 66 | } 67 | // Create the render target textures 68 | SDL_GPUTextureCreateInfo textureCreateInfo = { 69 | .type = SDL_GPU_TEXTURETYPE_2D, 70 | .width = 640, 71 | .height = 480, 72 | .layer_count_or_depth = 1, 73 | .num_levels = 1, 74 | .format = RTFormat, 75 | .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, 76 | .sample_count = sample_count 77 | }; 78 | if (sample_count == SDL_GPU_SAMPLECOUNT_1) 79 | { 80 | textureCreateInfo.usage |= SDL_GPU_TEXTUREUSAGE_SAMPLER; 81 | } 82 | MSAARenderTextures[SampleCounts] = SDL_CreateGPUTexture(context->Device, &textureCreateInfo); 83 | if (MSAARenderTextures[SampleCounts] == NULL) { 84 | SDL_Log("Failed to create MSAA render target texture!"); 85 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipelines[SampleCounts]); 86 | } 87 | SampleCounts += 1; 88 | } 89 | 90 | // Create resolve texture 91 | ResolveTexture = SDL_CreateGPUTexture( 92 | context->Device, 93 | &(SDL_GPUTextureCreateInfo) { 94 | .type = SDL_GPU_TEXTURETYPE_2D, 95 | .width = 640, 96 | .height = 480, 97 | .layer_count_or_depth = 1, 98 | .num_levels = 1, 99 | .format = RTFormat, 100 | .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER 101 | } 102 | ); 103 | 104 | // Clean up shader resources 105 | SDL_ReleaseGPUShader(context->Device, vertexShader); 106 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 107 | 108 | // Print the instructions 109 | SDL_Log("Press Left/Right to cycle between sample counts"); 110 | SDL_Log("Current sample count: %d", (1 << CurrentSampleCount)); 111 | 112 | return 0; 113 | } 114 | 115 | static int Update(Context* context) 116 | { 117 | int changed = 0; 118 | 119 | if (context->LeftPressed) 120 | { 121 | CurrentSampleCount -= 1; 122 | if (CurrentSampleCount < 0) 123 | { 124 | CurrentSampleCount = SampleCounts - 1; 125 | } 126 | changed = 1; 127 | } 128 | 129 | if (context->RightPressed) 130 | { 131 | CurrentSampleCount = (CurrentSampleCount + 1) % SampleCounts; 132 | changed = 1; 133 | } 134 | 135 | if (changed) 136 | { 137 | SDL_Log("Current sample count: %d", (1 << CurrentSampleCount)); 138 | } 139 | 140 | return 0; 141 | } 142 | 143 | static int Draw(Context* context) 144 | { 145 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 146 | if (cmdbuf == NULL) 147 | { 148 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 149 | return -1; 150 | } 151 | 152 | SDL_GPUTexture* swapchainTexture; 153 | Uint32 w, h; 154 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 155 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 156 | return -1; 157 | } 158 | 159 | if (swapchainTexture != NULL) 160 | { 161 | SDL_GPURenderPass* renderPass; 162 | SDL_GPUColorTargetInfo colorTargetInfo = { 163 | .texture = MSAARenderTextures[CurrentSampleCount], 164 | .clear_color = (SDL_FColor){ 1.0f, 1.0f, 1.0f, 1.0f }, 165 | .load_op = SDL_GPU_LOADOP_CLEAR, 166 | }; 167 | 168 | if (CurrentSampleCount == SDL_GPU_SAMPLECOUNT_1) 169 | { 170 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 171 | } 172 | else 173 | { 174 | colorTargetInfo.store_op = SDL_GPU_STOREOP_RESOLVE; 175 | colorTargetInfo.resolve_texture = ResolveTexture; 176 | } 177 | 178 | renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 179 | SDL_BindGPUGraphicsPipeline(renderPass, Pipelines[CurrentSampleCount]); 180 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 181 | SDL_EndGPURenderPass(renderPass); 182 | 183 | SDL_GPUTexture* blitSourceTexture = (colorTargetInfo.resolve_texture != NULL) ? colorTargetInfo.resolve_texture : colorTargetInfo.texture; 184 | SDL_BlitGPUTexture( 185 | cmdbuf, 186 | &(SDL_GPUBlitInfo){ 187 | .source.texture = blitSourceTexture, 188 | .source.x = 160, 189 | .source.w = 320, 190 | .source.h = 240, 191 | .destination.texture = swapchainTexture, 192 | .destination.w = w, 193 | .destination.h = h, 194 | .load_op = SDL_GPU_LOADOP_DONT_CARE, 195 | .filter = SDL_GPU_FILTER_LINEAR 196 | } 197 | ); 198 | } 199 | 200 | SDL_SubmitGPUCommandBuffer(cmdbuf); 201 | 202 | return 0; 203 | } 204 | 205 | static void Quit(Context* context) 206 | { 207 | for (int i = 0; i < SampleCounts; i += 1) 208 | { 209 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipelines[i]); 210 | SDL_ReleaseGPUTexture(context->Device, MSAARenderTextures[i]); 211 | } 212 | SDL_ReleaseGPUTexture(context->Device, ResolveTexture); 213 | 214 | CurrentSampleCount = 0; 215 | 216 | CommonQuit(context); 217 | } 218 | 219 | Example TriangleMSAA_Example = { "TriangleMSAA", Init, Update, Draw, Quit }; 220 | -------------------------------------------------------------------------------- /Examples/main.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | #include 3 | 4 | static Example* Examples[] = 5 | { 6 | &ClearScreen_Example, 7 | #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) 8 | &ClearScreenMultiWindow_Example, 9 | #endif 10 | &BasicTriangle_Example, 11 | &BasicVertexBuffer_Example, 12 | &CullMode_Example, 13 | &BasicStencil_Example, 14 | &InstancedIndexed_Example, 15 | &TexturedQuad_Example, 16 | &TexturedAnimatedQuad_Example, 17 | &Clear3DSlice_Example, 18 | &BasicCompute_Example, 19 | &ComputeUniforms_Example, 20 | &ToneMapping_Example, 21 | &CustomSampling_Example, 22 | &DrawIndirect_Example, 23 | &ComputeSampler_Example, 24 | &CopyAndReadback_Example, 25 | &CopyConsistency_Example, 26 | &Texture2DArray_Example, 27 | &TriangleMSAA_Example, 28 | &Cubemap_Example, 29 | &WindowResize_Example, 30 | &Blit2DArray_Example, 31 | &BlitCube_Example, 32 | &BlitMirror_Example, 33 | &GenerateMipmaps_Example, 34 | &Latency_Example, 35 | &DepthSampler_Example, 36 | &ComputeSpriteBatch_Example, 37 | &PullSpriteBatch_Example, 38 | &TextureTypeTest_Example, 39 | &CompressedTextures_Example, 40 | }; 41 | 42 | bool AppLifecycleWatcher(void *userdata, SDL_Event *event) 43 | { 44 | /* This callback may be on a different thread, so let's 45 | * push these events as USER events so they appear 46 | * in the main thread's event loop. 47 | * 48 | * That allows us to cancel drawing before/after we finish 49 | * drawing a frame, rather than mid-draw (which can crash!). 50 | */ 51 | if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) 52 | { 53 | SDL_Event evt; 54 | evt.type = SDL_EVENT_USER; 55 | evt.user.code = 0; 56 | SDL_PushEvent(&evt); 57 | } 58 | else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) 59 | { 60 | SDL_Event evt; 61 | evt.type = SDL_EVENT_USER; 62 | evt.user.code = 1; 63 | SDL_PushEvent(&evt); 64 | } 65 | return false; 66 | } 67 | 68 | int main(int argc, char **argv) 69 | { 70 | Context context = { 0 }; 71 | int exampleIndex = -1; 72 | int gotoExampleIndex = 0; 73 | int quit = 0; 74 | float lastTime = 0; 75 | 76 | for (int i = 1; i < argc; i += 1) 77 | { 78 | if (SDL_strcmp(argv[i], "-name") == 0 && argc > i + 1) 79 | { 80 | const char* exampleName = argv[i + 1]; 81 | int foundExample = 0; 82 | 83 | for (int j = 0; j < SDL_arraysize(Examples); j += 1) 84 | { 85 | if (SDL_strcmp(Examples[j]->Name, exampleName) == 0) 86 | { 87 | gotoExampleIndex = j; 88 | foundExample = 1; 89 | break; 90 | } 91 | } 92 | 93 | if (!foundExample) 94 | { 95 | SDL_Log("No example named '%s' exists.", exampleName); 96 | return 1; 97 | } 98 | } 99 | } 100 | 101 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) 102 | { 103 | SDL_Log("Failed to initialize SDL: %s", SDL_GetError()); 104 | return 1; 105 | } 106 | 107 | InitializeAssetLoader(); 108 | SDL_AddEventWatch(AppLifecycleWatcher, NULL); 109 | 110 | SDL_Log("Welcome to the SDL_GPU example suite!"); 111 | SDL_Log("Press A/D (or LB/RB) to move between examples!"); 112 | 113 | SDL_Gamepad* gamepad = NULL; 114 | bool canDraw = true; 115 | 116 | while (!quit) 117 | { 118 | context.LeftPressed = 0; 119 | context.RightPressed = 0; 120 | context.DownPressed = 0; 121 | context.UpPressed = 0; 122 | 123 | SDL_Event evt; 124 | while (SDL_PollEvent(&evt)) 125 | { 126 | if (evt.type == SDL_EVENT_QUIT) 127 | { 128 | if (exampleIndex != -1) 129 | { 130 | Examples[exampleIndex]->Quit(&context); 131 | } 132 | quit = 1; 133 | } 134 | else if (evt.type == SDL_EVENT_GAMEPAD_ADDED) 135 | { 136 | if (gamepad == NULL) 137 | { 138 | gamepad = SDL_OpenGamepad(evt.gdevice.which); 139 | } 140 | } 141 | else if (evt.type == SDL_EVENT_GAMEPAD_REMOVED) 142 | { 143 | if (evt.gdevice.which == SDL_GetGamepadID(gamepad)) 144 | { 145 | SDL_CloseGamepad(gamepad); 146 | } 147 | } 148 | else if (evt.type == SDL_EVENT_USER) 149 | { 150 | if (evt.user.code == 0) 151 | { 152 | #ifdef SDL_PLATFORM_GDK 153 | SDL_GDKSuspendGPU(context.Device); 154 | canDraw = false; 155 | SDL_GDKSuspendComplete(); 156 | #endif 157 | } 158 | else if (evt.user.code == 1) 159 | { 160 | #ifdef SDL_PLATFORM_GDK 161 | SDL_GDKResumeGPU(context.Device); 162 | canDraw = true; 163 | #endif 164 | } 165 | } 166 | else if (evt.type == SDL_EVENT_KEY_DOWN) 167 | { 168 | if (evt.key.key == SDLK_D) 169 | { 170 | gotoExampleIndex = exampleIndex + 1; 171 | if (gotoExampleIndex >= SDL_arraysize(Examples)) { 172 | gotoExampleIndex = 0; 173 | } 174 | } 175 | else if (evt.key.key == SDLK_A) 176 | { 177 | gotoExampleIndex = exampleIndex - 1; 178 | if (gotoExampleIndex < 0) { 179 | gotoExampleIndex = SDL_arraysize(Examples) - 1; 180 | } 181 | } 182 | else if (evt.key.key == SDLK_LEFT) 183 | { 184 | context.LeftPressed = true; 185 | } 186 | else if (evt.key.key == SDLK_RIGHT) 187 | { 188 | context.RightPressed = true; 189 | } 190 | else if (evt.key.key == SDLK_DOWN) 191 | { 192 | context.DownPressed = true; 193 | } 194 | else if (evt.key.key == SDLK_UP) 195 | { 196 | context.UpPressed = true; 197 | } 198 | } 199 | else if (evt.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) 200 | { 201 | if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER) 202 | { 203 | gotoExampleIndex = exampleIndex + 1; 204 | if (gotoExampleIndex >= SDL_arraysize(Examples)) { 205 | gotoExampleIndex = 0; 206 | } 207 | } 208 | else if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_LEFT_SHOULDER) 209 | { 210 | gotoExampleIndex = exampleIndex - 1; 211 | if (gotoExampleIndex < 0) { 212 | gotoExampleIndex = SDL_arraysize(Examples) - 1; 213 | } 214 | } 215 | else if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_LEFT) 216 | { 217 | context.LeftPressed = true; 218 | } 219 | else if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT) 220 | { 221 | context.RightPressed = true; 222 | } 223 | else if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_DOWN) 224 | { 225 | context.DownPressed = true; 226 | } 227 | else if (evt.gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_UP) 228 | { 229 | context.UpPressed = true; 230 | } 231 | } 232 | } 233 | if (quit) 234 | { 235 | break; 236 | } 237 | 238 | if (gotoExampleIndex != -1) 239 | { 240 | if (exampleIndex != -1) 241 | { 242 | Examples[exampleIndex]->Quit(&context); 243 | SDL_zero(context); 244 | } 245 | 246 | exampleIndex = gotoExampleIndex; 247 | context.ExampleName = Examples[exampleIndex]->Name; 248 | SDL_Log("STARTING EXAMPLE: %s", context.ExampleName); 249 | if (Examples[exampleIndex]->Init(&context) < 0) 250 | { 251 | SDL_Log("Init failed!"); 252 | return 1; 253 | } 254 | 255 | gotoExampleIndex = -1; 256 | } 257 | 258 | float newTime = SDL_GetTicks() / 1000.0f; 259 | context.DeltaTime = newTime - lastTime; 260 | lastTime = newTime; 261 | 262 | if (Examples[exampleIndex]->Update(&context) < 0) 263 | { 264 | SDL_Log("Update failed!"); 265 | return 1; 266 | } 267 | 268 | if (canDraw) 269 | { 270 | if (Examples[exampleIndex]->Draw(&context) < 0) 271 | { 272 | SDL_Log("Draw failed!"); 273 | return 1; 274 | } 275 | } 276 | } 277 | 278 | return 0; 279 | } 280 | -------------------------------------------------------------------------------- /Examples/Latency.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUTexture *LagTexture; 4 | static int LagX = 1; 5 | static bool CaptureCursor = false; 6 | static int allowedFramesInFlight; 7 | static int fullscreen; 8 | 9 | static int Init(Context* context) 10 | { 11 | int result = CommonInit(context, 0); 12 | if (result < 0) 13 | { 14 | return result; 15 | } 16 | 17 | LagTexture = SDL_CreateGPUTexture( 18 | context->Device, 19 | &(SDL_GPUTextureCreateInfo){ 20 | .type = SDL_GPU_TEXTURETYPE_2D, 21 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 22 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER, 23 | .width = 8, 24 | .height = 32, 25 | .layer_count_or_depth = 1, 26 | .num_levels = 1 27 | } 28 | ); 29 | 30 | Uint32 byteCount = 8 * 32 * 4; 31 | SDL_GPUTransferBuffer *textureTransferBuffer = SDL_CreateGPUTransferBuffer( 32 | context->Device, 33 | &(SDL_GPUTransferBufferCreateInfo) { 34 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 35 | .size = byteCount 36 | } 37 | ); 38 | Uint8* textureTransferData = SDL_MapGPUTransferBuffer( 39 | context->Device, 40 | textureTransferBuffer, 41 | false 42 | ); 43 | 44 | SDL_Surface* imageData = LoadImage("latency.bmp", 4); 45 | if (imageData == NULL) 46 | { 47 | SDL_Log("Could not load image data!"); 48 | return -1; 49 | } 50 | SDL_memcpy(textureTransferData, imageData->pixels, byteCount); 51 | SDL_DestroySurface(imageData); 52 | 53 | SDL_UnmapGPUTransferBuffer(context->Device, textureTransferBuffer); 54 | 55 | SDL_GPUCommandBuffer *cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 56 | SDL_GPUCopyPass *copyPass = SDL_BeginGPUCopyPass(cmdbuf); 57 | SDL_UploadToGPUTexture( 58 | copyPass, 59 | &(SDL_GPUTextureTransferInfo){ 60 | .transfer_buffer = textureTransferBuffer 61 | }, 62 | &(SDL_GPUTextureRegion) { 63 | .texture = LagTexture, 64 | .w = 8, 65 | .h = 32, 66 | .d = 1 67 | }, 68 | false 69 | ); 70 | SDL_EndGPUCopyPass(copyPass); 71 | 72 | SDL_SubmitGPUCommandBuffer(cmdbuf); 73 | 74 | SDL_ReleaseGPUTransferBuffer(context->Device, textureTransferBuffer); 75 | 76 | SDL_Log("Press Left/Right to toggle capturing the mouse cursor."); 77 | SDL_Log("Press Down to change the number of allowed frames in flight."); 78 | SDL_Log("Press Up to toggle fullscreen mode."); 79 | SDL_Log("When the mouse cursor is captured the color directly above the cursor's point in the " 80 | "result of the test."); 81 | SDL_Log("Negative lag can occur when the cursor is below the tear line when tearing is enabled " 82 | "as the cursor is only moved during V-blank so it lags the framebuffer update."); 83 | SDL_Log(" Gray: -1 frames lag"); 84 | SDL_Log(" White: 0 frames lag"); 85 | SDL_Log(" Green: 1 frames lag"); 86 | SDL_Log(" Yellow: 2 frames lag"); 87 | SDL_Log(" Red: 3 frames lag"); 88 | SDL_Log(" Cyan: 4 frames lag"); 89 | SDL_Log(" Purple: 5 frames lag"); 90 | SDL_Log(" Blue: 6 frames lag"); 91 | 92 | allowedFramesInFlight = 2; 93 | fullscreen = false; 94 | 95 | SDL_SetGPUAllowedFramesInFlight(context->Device, allowedFramesInFlight); 96 | return 0; 97 | } 98 | 99 | static int Update(Context* context) 100 | { 101 | if (context->LeftPressed || context->RightPressed) 102 | { 103 | CaptureCursor = !CaptureCursor; 104 | } 105 | 106 | if (context->DownPressed) 107 | { 108 | allowedFramesInFlight = SDL_clamp((allowedFramesInFlight + 1) % 4, 1, 3); 109 | SDL_SetGPUAllowedFramesInFlight(context->Device, allowedFramesInFlight); 110 | SDL_Log("Allowed frames in flight: %i", allowedFramesInFlight); 111 | } 112 | 113 | if (context->UpPressed) 114 | { 115 | fullscreen = !fullscreen; 116 | SDL_SetWindowFullscreen(context->Window, fullscreen); 117 | } 118 | 119 | return 0; 120 | } 121 | 122 | static int Draw(Context* context) 123 | { 124 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 125 | if (cmdbuf == NULL) 126 | { 127 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 128 | return -1; 129 | } 130 | 131 | SDL_GPUTexture* swapchainTexture; 132 | Uint32 w, h; 133 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 134 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 135 | return -1; 136 | } 137 | 138 | if (swapchainTexture != NULL) 139 | { 140 | // Get the current mouse cursor position. We use SDL_GetGlobalMouseState() as it actively 141 | // queries the latest position of the mouse unlike SDL_GetMouseState() which uses a cached 142 | // value. 143 | float cursorX, cursorY; 144 | SDL_GetGlobalMouseState(&cursorX, &cursorY); 145 | int winX, winY; 146 | SDL_GetWindowPosition(context->Window, &winX, &winY); 147 | cursorX -= winX; 148 | cursorY -= winY; 149 | 150 | if (CaptureCursor) 151 | { 152 | // Move the cursor to a known position. 153 | cursorX = LagX; 154 | SDL_WarpMouseInWindow(context->Window, cursorX, cursorY); 155 | if (LagX >= w - 8) 156 | { 157 | LagX = 1; 158 | } 159 | else 160 | { 161 | ++LagX; 162 | } 163 | } 164 | 165 | // Draw a sprite directly under the cursor if permitted by the blitting engine. 166 | if (cursorX >= 1 && cursorX <= w - 8 && cursorY >= 5 && cursorY <= h - 27) 167 | { 168 | SDL_BlitGPUTexture( 169 | cmdbuf, 170 | &(SDL_GPUBlitInfo){ 171 | .source.texture = LagTexture, 172 | .source.w = 8, 173 | .source.h = 32, 174 | .source.mip_level = 0, 175 | .destination.texture = swapchainTexture, 176 | .destination.x = cursorX - 1, 177 | .destination.y = cursorY - 5, 178 | .destination.w = 8, 179 | .destination.h = 32, 180 | .load_op = SDL_GPU_LOADOP_CLEAR, 181 | .clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f } 182 | } 183 | ); 184 | } else { 185 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 186 | colorTargetInfo.texture = swapchainTexture; 187 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 188 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 189 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 190 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 191 | SDL_EndGPURenderPass(renderPass); 192 | } 193 | } 194 | 195 | SDL_SubmitGPUCommandBuffer(cmdbuf); 196 | 197 | return 0; 198 | } 199 | 200 | static void Quit(Context* context) 201 | { 202 | SDL_ReleaseGPUTexture(context->Device, LagTexture); 203 | CommonQuit(context); 204 | } 205 | 206 | Example Latency_Example = { "Latency", Init, Update, Draw, Quit }; 207 | -------------------------------------------------------------------------------- /Examples/BasicCompute.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* DrawPipeline; 4 | static SDL_GPUTexture* Texture; 5 | static SDL_GPUSampler* Sampler; 6 | static SDL_GPUBuffer* VertexBuffer; 7 | 8 | static int Init(Context* context) 9 | { 10 | int result = CommonInit(context, 0); 11 | if (result < 0) 12 | { 13 | return result; 14 | } 15 | 16 | SDL_GPUShader *vertexShader = LoadShader(context->Device, "TexturedQuad.vert", 0, 0, 0, 0); 17 | if (vertexShader == NULL) 18 | { 19 | SDL_Log("Failed to create vertex shader!"); 20 | return -1; 21 | } 22 | 23 | SDL_GPUShader *fragmentShader = LoadShader(context->Device, "TexturedQuad.frag", 1, 0, 0, 0); 24 | if (fragmentShader == NULL) 25 | { 26 | SDL_Log("Failed to create fragment shader!"); 27 | return -1; 28 | } 29 | 30 | SDL_GPUComputePipeline* fillTexturePipeline = CreateComputePipelineFromShader( 31 | context->Device, 32 | "FillTexture.comp", 33 | &(SDL_GPUComputePipelineCreateInfo) { 34 | .num_readwrite_storage_textures = 1, 35 | .threadcount_x = 8, 36 | .threadcount_y = 8, 37 | .threadcount_z = 1, 38 | } 39 | ); 40 | 41 | DrawPipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &(SDL_GPUGraphicsPipelineCreateInfo){ 42 | .target_info = { 43 | .num_color_targets = 1, 44 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 45 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 46 | }} 47 | }, 48 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 49 | .vertex_input_state = (SDL_GPUVertexInputState){ 50 | .num_vertex_buffers = 1, 51 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 52 | .slot = 0, 53 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 54 | .instance_step_rate = 0, 55 | .pitch = sizeof(PositionTextureVertex) 56 | }}, 57 | .num_vertex_attributes = 2, 58 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 59 | .buffer_slot = 0, 60 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 61 | .location = 0, 62 | .offset = 0 63 | }, { 64 | .buffer_slot = 0, 65 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, 66 | .location = 1, 67 | .offset = sizeof(float) * 3 68 | }} 69 | }, 70 | .vertex_shader = vertexShader, 71 | .fragment_shader = fragmentShader 72 | }); 73 | 74 | SDL_ReleaseGPUShader(context->Device, vertexShader); 75 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 76 | 77 | int w, h; 78 | SDL_GetWindowSizeInPixels(context->Window, &w, &h); 79 | 80 | Texture = SDL_CreateGPUTexture(context->Device, &(SDL_GPUTextureCreateInfo){ 81 | .type = SDL_GPU_TEXTURETYPE_2D, 82 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 83 | .width = w, 84 | .height = h, 85 | .layer_count_or_depth = 1, 86 | .num_levels = 1, 87 | .usage = SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE | SDL_GPU_TEXTUREUSAGE_SAMPLER 88 | }); 89 | 90 | Sampler = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 91 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 92 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT 93 | }); 94 | 95 | VertexBuffer = SDL_CreateGPUBuffer( 96 | context->Device, 97 | &(SDL_GPUBufferCreateInfo) { 98 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 99 | .size = sizeof(PositionTextureVertex) * 6 100 | } 101 | ); 102 | 103 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 104 | context->Device, 105 | &(SDL_GPUTransferBufferCreateInfo) { 106 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 107 | .size = sizeof(PositionTextureVertex) * 6 108 | } 109 | ); 110 | 111 | PositionTextureVertex* transferData = SDL_MapGPUTransferBuffer( 112 | context->Device, 113 | transferBuffer, 114 | false 115 | ); 116 | 117 | transferData[0] = (PositionTextureVertex) { -1, -1, 0, 0, 0 }; 118 | transferData[1] = (PositionTextureVertex) { 1, -1, 0, 1, 0 }; 119 | transferData[2] = (PositionTextureVertex) { 1, 1, 0, 1, 1 }; 120 | transferData[3] = (PositionTextureVertex) { -1, -1, 0, 0, 0 }; 121 | transferData[4] = (PositionTextureVertex) { 1, 1, 0, 1, 1 }; 122 | transferData[5] = (PositionTextureVertex) { -1, 1, 0, 0, 1 }; 123 | 124 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 125 | 126 | SDL_GPUCommandBuffer* cmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 127 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdBuf); 128 | 129 | SDL_UploadToGPUBuffer( 130 | copyPass, 131 | &(SDL_GPUTransferBufferLocation) { 132 | .transfer_buffer = transferBuffer, 133 | .offset = 0 134 | }, 135 | &(SDL_GPUBufferRegion) { 136 | .buffer = VertexBuffer, 137 | .offset = 0, 138 | .size = sizeof(PositionTextureVertex) * 6 139 | }, 140 | false 141 | ); 142 | 143 | SDL_EndGPUCopyPass(copyPass); 144 | 145 | SDL_GPUComputePass* computePass = SDL_BeginGPUComputePass( 146 | cmdBuf, 147 | (SDL_GPUStorageTextureReadWriteBinding[]){{ 148 | .texture = Texture 149 | }}, 150 | 1, 151 | NULL, 152 | 0 153 | ); 154 | 155 | SDL_BindGPUComputePipeline(computePass, fillTexturePipeline); 156 | SDL_DispatchGPUCompute(computePass, w / 8, h / 8, 1); 157 | SDL_EndGPUComputePass(computePass); 158 | 159 | SDL_SubmitGPUCommandBuffer(cmdBuf); 160 | 161 | SDL_ReleaseGPUComputePipeline(context->Device, fillTexturePipeline); 162 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 163 | 164 | return 0; 165 | } 166 | 167 | static int Update(Context* context) 168 | { 169 | return 0; 170 | } 171 | 172 | static int Draw(Context* context) 173 | { 174 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 175 | if (cmdbuf == NULL) 176 | { 177 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 178 | return -1; 179 | } 180 | 181 | SDL_GPUTexture* swapchainTexture; 182 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 183 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 184 | return -1; 185 | } 186 | 187 | if (swapchainTexture != NULL) 188 | { 189 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass( 190 | cmdbuf, 191 | (SDL_GPUColorTargetInfo[]){{ 192 | .texture = swapchainTexture, 193 | .load_op = SDL_GPU_LOADOP_CLEAR, 194 | .store_op = SDL_GPU_STOREOP_STORE, 195 | .clear_color.a = 1, 196 | .cycle = false 197 | }}, 198 | 1, 199 | NULL 200 | ); 201 | 202 | SDL_BindGPUGraphicsPipeline(renderPass, DrawPipeline); 203 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBuffer, .offset = 0 }, 1); 204 | SDL_BindGPUFragmentSamplers(renderPass, 0, &(SDL_GPUTextureSamplerBinding){ .texture = Texture, .sampler = Sampler }, 1); 205 | SDL_DrawGPUPrimitives(renderPass, 6, 1, 0, 0); 206 | 207 | SDL_EndGPURenderPass(renderPass); 208 | } 209 | 210 | SDL_SubmitGPUCommandBuffer(cmdbuf); 211 | 212 | return 0; 213 | } 214 | 215 | static void Quit(Context* context) 216 | { 217 | SDL_ReleaseGPUGraphicsPipeline(context->Device, DrawPipeline); 218 | SDL_ReleaseGPUTexture(context->Device, Texture); 219 | SDL_ReleaseGPUSampler(context->Device, Sampler); 220 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 221 | 222 | CommonQuit(context); 223 | } 224 | 225 | Example BasicCompute_Example = { "BasicCompute", Init, Update, Draw, Quit }; 226 | -------------------------------------------------------------------------------- /Examples/InstancedIndexed.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* Pipeline; 4 | static SDL_GPUBuffer* VertexBuffer; 5 | static SDL_GPUBuffer* IndexBuffer; 6 | 7 | static bool UseVertexOffset = false; 8 | static bool UseIndexOffset = false; 9 | static bool UseIndexBuffer = true; 10 | 11 | static int Init(Context* context) 12 | { 13 | int result = CommonInit(context, 0); 14 | if (result < 0) 15 | { 16 | return result; 17 | } 18 | 19 | // Create the shaders 20 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "PositionColorInstanced.vert", 0, 0, 0, 0); 21 | if (vertexShader == NULL) 22 | { 23 | SDL_Log("Failed to create vertex shader!"); 24 | return -1; 25 | } 26 | 27 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 28 | if (fragmentShader == NULL) 29 | { 30 | SDL_Log("Failed to create fragment shader!"); 31 | return -1; 32 | } 33 | 34 | // Create the pipeline 35 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 36 | .target_info = { 37 | .num_color_targets = 1, 38 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 39 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 40 | }}, 41 | }, 42 | // This is set up to match the vertex shader layout! 43 | .vertex_input_state = (SDL_GPUVertexInputState){ 44 | .num_vertex_buffers = 1, 45 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 46 | .slot = 0, 47 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 48 | .instance_step_rate = 0, 49 | .pitch = sizeof(PositionColorVertex) 50 | }}, 51 | .num_vertex_attributes = 2, 52 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 53 | .buffer_slot = 0, 54 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 55 | .location = 0, 56 | .offset = 0 57 | }, { 58 | .buffer_slot = 0, 59 | .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, 60 | .location = 1, 61 | .offset = sizeof(float) * 3 62 | }} 63 | }, 64 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 65 | .vertex_shader = vertexShader, 66 | .fragment_shader = fragmentShader 67 | }; 68 | 69 | Pipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 70 | if (Pipeline == NULL) 71 | { 72 | SDL_Log("Failed to create pipeline!"); 73 | return -1; 74 | } 75 | 76 | SDL_ReleaseGPUShader(context->Device, vertexShader); 77 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 78 | 79 | // Create the vertex and index buffers 80 | VertexBuffer = SDL_CreateGPUBuffer( 81 | context->Device, 82 | &(SDL_GPUBufferCreateInfo) { 83 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 84 | .size = sizeof(PositionColorVertex) * 9 85 | } 86 | ); 87 | 88 | IndexBuffer = SDL_CreateGPUBuffer( 89 | context->Device, 90 | &(SDL_GPUBufferCreateInfo) { 91 | .usage = SDL_GPU_BUFFERUSAGE_INDEX, 92 | .size = sizeof(Uint16) * 6 93 | } 94 | ); 95 | 96 | // Set the buffer data 97 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 98 | context->Device, 99 | &(SDL_GPUTransferBufferCreateInfo) { 100 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 101 | .size = (sizeof(PositionColorVertex) * 9) + (sizeof(Uint16) * 6), 102 | } 103 | ); 104 | 105 | PositionColorVertex* transferData = SDL_MapGPUTransferBuffer( 106 | context->Device, 107 | transferBuffer, 108 | false 109 | ); 110 | 111 | transferData[0] = (PositionColorVertex) { -1, -1, 0, 255, 0, 0, 255 }; 112 | transferData[1] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 113 | transferData[2] = (PositionColorVertex) { 0, 1, 0, 0, 0, 255, 255 }; 114 | 115 | transferData[3] = (PositionColorVertex) { -1, -1, 0, 255, 165, 0, 255 }; 116 | transferData[4] = (PositionColorVertex) { 1, -1, 0, 0, 128, 0, 255 }; 117 | transferData[5] = (PositionColorVertex) { 0, 1, 0, 0, 255, 255, 255 }; 118 | 119 | transferData[6] = (PositionColorVertex) { -1, -1, 0, 255, 255, 255, 255 }; 120 | transferData[7] = (PositionColorVertex) { 1, -1, 0, 255, 255, 255, 255 }; 121 | transferData[8] = (PositionColorVertex) { 0, 1, 0, 255, 255, 255, 255 }; 122 | 123 | Uint16* indexData = (Uint16*) &transferData[9]; 124 | for (Uint16 i = 0; i < 6; i += 1) 125 | { 126 | indexData[i] = i; 127 | } 128 | 129 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 130 | 131 | // Upload the transfer data to the vertex and index buffer 132 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 133 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 134 | 135 | SDL_UploadToGPUBuffer( 136 | copyPass, 137 | &(SDL_GPUTransferBufferLocation) { 138 | .transfer_buffer = transferBuffer, 139 | .offset = 0 140 | }, 141 | &(SDL_GPUBufferRegion) { 142 | .buffer = VertexBuffer, 143 | .offset = 0, 144 | .size = sizeof(PositionColorVertex) * 9 145 | }, 146 | false 147 | ); 148 | 149 | SDL_UploadToGPUBuffer( 150 | copyPass, 151 | &(SDL_GPUTransferBufferLocation) { 152 | .transfer_buffer = transferBuffer, 153 | .offset = sizeof(PositionColorVertex) * 9 154 | }, 155 | &(SDL_GPUBufferRegion) { 156 | .buffer = IndexBuffer, 157 | .offset = 0, 158 | .size = sizeof(Uint16) * 6 159 | }, 160 | false 161 | ); 162 | 163 | SDL_EndGPUCopyPass(copyPass); 164 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 165 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 166 | 167 | return 0; 168 | } 169 | 170 | static int Update(Context* context) 171 | { 172 | if (context->LeftPressed) 173 | { 174 | UseVertexOffset = !UseVertexOffset; 175 | SDL_Log("Using vertex offset: %s", UseVertexOffset ? "true" : "false"); 176 | } 177 | 178 | if (context->RightPressed) 179 | { 180 | UseIndexOffset = !UseIndexOffset; 181 | SDL_Log("Using index offset: %s", UseIndexOffset ? "true" : "false"); 182 | } 183 | 184 | if (context->UpPressed) 185 | { 186 | UseIndexBuffer = !UseIndexBuffer; 187 | SDL_Log("Using index buffer: %s", UseIndexBuffer ? "true" : "false"); 188 | } 189 | 190 | return 0; 191 | } 192 | 193 | static int Draw(Context* context) 194 | { 195 | Uint32 vertexOffset = UseVertexOffset ? 3 : 0; 196 | Uint32 indexOffset = UseIndexOffset ? 3 : 0; 197 | 198 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 199 | if (cmdbuf == NULL) 200 | { 201 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 202 | return -1; 203 | } 204 | 205 | SDL_GPUTexture* swapchainTexture; 206 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 207 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 208 | return -1; 209 | } 210 | 211 | if (swapchainTexture != NULL) 212 | { 213 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 214 | colorTargetInfo.texture = swapchainTexture; 215 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 216 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 217 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 218 | 219 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 220 | 221 | SDL_BindGPUGraphicsPipeline(renderPass, Pipeline); 222 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBuffer, .offset = 0 }, 1); 223 | 224 | if (UseIndexBuffer) 225 | { 226 | SDL_BindGPUIndexBuffer(renderPass, &(SDL_GPUBufferBinding){ .buffer = IndexBuffer, .offset = 0 }, SDL_GPU_INDEXELEMENTSIZE_16BIT); 227 | SDL_DrawGPUIndexedPrimitives(renderPass, 3, 16, indexOffset, vertexOffset, 0); 228 | } else { 229 | SDL_DrawGPUPrimitives(renderPass, 3, 16, vertexOffset, 0); 230 | } 231 | 232 | SDL_EndGPURenderPass(renderPass); 233 | } 234 | 235 | SDL_SubmitGPUCommandBuffer(cmdbuf); 236 | 237 | return 0; 238 | } 239 | 240 | static void Quit(Context* context) 241 | { 242 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipeline); 243 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 244 | SDL_ReleaseGPUBuffer(context->Device, IndexBuffer); 245 | 246 | UseVertexOffset = false; 247 | UseIndexOffset = false; 248 | UseIndexBuffer = true; 249 | 250 | CommonQuit(context); 251 | } 252 | 253 | Example InstancedIndexed_Example = { "InstancedIndexed", Init, Update, Draw, Quit }; 254 | -------------------------------------------------------------------------------- /Examples/CullMode.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static const char* ModeNames[] = 4 | { 5 | "CCW_CullNone", 6 | "CCW_CullFront", 7 | "CCW_CullBack", 8 | "CW_CullNone", 9 | "CW_CullFront", 10 | "CW_CullBack" 11 | }; 12 | 13 | static SDL_GPUGraphicsPipeline* Pipelines[SDL_arraysize(ModeNames)]; 14 | static int CurrentMode = 0; 15 | 16 | static SDL_GPUBuffer* VertexBufferCW; 17 | static SDL_GPUBuffer* VertexBufferCCW; 18 | 19 | static int Init(Context* context) 20 | { 21 | int result = CommonInit(context, 0); 22 | if (result < 0) 23 | { 24 | return result; 25 | } 26 | 27 | // Create the shaders 28 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "PositionColor.vert", 0, 0, 0, 0); 29 | if (vertexShader == NULL) 30 | { 31 | SDL_Log("Failed to create vertex shader!"); 32 | return -1; 33 | } 34 | 35 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 36 | if (fragmentShader == NULL) 37 | { 38 | SDL_Log("Failed to create fragment shader!"); 39 | return -1; 40 | } 41 | 42 | // Create the pipelines 43 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 44 | .target_info = { 45 | .num_color_targets = 1, 46 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 47 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 48 | }}, 49 | }, 50 | .vertex_input_state = (SDL_GPUVertexInputState){ 51 | .num_vertex_buffers = 1, 52 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 53 | .slot = 0, 54 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 55 | .instance_step_rate = 0, 56 | .pitch = sizeof(PositionColorVertex) 57 | }}, 58 | .num_vertex_attributes = 2, 59 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 60 | .buffer_slot = 0, 61 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 62 | .location = 0, 63 | .offset = 0 64 | }, { 65 | .buffer_slot = 0, 66 | .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, 67 | .location = 1, 68 | .offset = sizeof(float) * 3 69 | }} 70 | }, 71 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 72 | .vertex_shader = vertexShader, 73 | .fragment_shader = fragmentShader, 74 | }; 75 | 76 | for (int i = 0; i < SDL_arraysize(Pipelines); i += 1) 77 | { 78 | pipelineCreateInfo.rasterizer_state.cull_mode = (SDL_GPUCullMode) (i % 3); 79 | pipelineCreateInfo.rasterizer_state.front_face = (i > 2) ? 80 | SDL_GPU_FRONTFACE_CLOCKWISE : 81 | SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE; 82 | 83 | Pipelines[i] = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 84 | if (Pipelines[i] == NULL) 85 | { 86 | SDL_Log("Failed to create pipeline!"); 87 | return -1; 88 | } 89 | } 90 | 91 | // Clean up shader resources 92 | SDL_ReleaseGPUShader(context->Device, vertexShader); 93 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 94 | 95 | // Create the vertex buffers. They're the same except for the vertex order. 96 | // FIXME: Needs error handling! 97 | VertexBufferCW = SDL_CreateGPUBuffer( 98 | context->Device, 99 | &(SDL_GPUBufferCreateInfo) { 100 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 101 | .size = sizeof(PositionColorVertex) * 3 102 | } 103 | ); 104 | VertexBufferCCW = SDL_CreateGPUBuffer( 105 | context->Device, 106 | &(SDL_GPUBufferCreateInfo) { 107 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 108 | .size = sizeof(PositionColorVertex) * 3 109 | } 110 | ); 111 | 112 | // Set up the transfer buffer 113 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 114 | context->Device, 115 | &(SDL_GPUTransferBufferCreateInfo) { 116 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 117 | .size = sizeof(PositionColorVertex) * 6 118 | } 119 | ); 120 | 121 | PositionColorVertex* transferData = SDL_MapGPUTransferBuffer( 122 | context->Device, 123 | transferBuffer, 124 | false 125 | ); 126 | 127 | transferData[0] = (PositionColorVertex) { -1, -1, 0, 255, 0, 0, 255 }; 128 | transferData[1] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 129 | transferData[2] = (PositionColorVertex) { 0, 1, 0, 0, 0, 255, 255 }; 130 | transferData[3] = (PositionColorVertex) { 0, 1, 0, 255, 0, 0, 255 }; 131 | transferData[4] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 132 | transferData[5] = (PositionColorVertex) { -1, -1, 0, 0, 0, 255, 255 }; 133 | 134 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 135 | 136 | // Upload the transfer data to the vertex buffer 137 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 138 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 139 | 140 | SDL_UploadToGPUBuffer( 141 | copyPass, 142 | &(SDL_GPUTransferBufferLocation) { 143 | .transfer_buffer = transferBuffer, 144 | .offset = 0 145 | }, 146 | &(SDL_GPUBufferRegion) { 147 | .buffer = VertexBufferCW, 148 | .offset = 0, 149 | .size = sizeof(PositionColorVertex) * 3 150 | }, 151 | false 152 | ); 153 | SDL_UploadToGPUBuffer( 154 | copyPass, 155 | &(SDL_GPUTransferBufferLocation) { 156 | .transfer_buffer = transferBuffer, 157 | .offset = sizeof(PositionColorVertex) * 3 158 | }, 159 | &(SDL_GPUBufferRegion) { 160 | .buffer = VertexBufferCCW, 161 | .offset = 0, 162 | .size = sizeof(PositionColorVertex) * 3 163 | }, 164 | false 165 | ); 166 | 167 | SDL_EndGPUCopyPass(copyPass); 168 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 169 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 170 | 171 | // Finally, print instructions! 172 | SDL_Log("Press Left/Right to switch between modes"); 173 | SDL_Log("Current Mode: %s", ModeNames[0]); 174 | 175 | return 0; 176 | } 177 | 178 | static int Update(Context* context) 179 | { 180 | if (context->LeftPressed) 181 | { 182 | CurrentMode -= 1; 183 | if (CurrentMode < 0) 184 | { 185 | CurrentMode = SDL_arraysize(Pipelines) - 1; 186 | } 187 | SDL_Log("Current Mode: %s", ModeNames[CurrentMode]); 188 | } 189 | 190 | if (context->RightPressed) 191 | { 192 | CurrentMode = (CurrentMode + 1) % SDL_arraysize(Pipelines); 193 | SDL_Log("Current Mode: %s", ModeNames[CurrentMode]); 194 | } 195 | 196 | return 0; 197 | } 198 | 199 | static int Draw(Context* context) 200 | { 201 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 202 | if (cmdbuf == NULL) 203 | { 204 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 205 | return -1; 206 | } 207 | 208 | SDL_GPUTexture* swapchainTexture; 209 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 210 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 211 | return -1; 212 | } 213 | 214 | if (swapchainTexture != NULL) 215 | { 216 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 217 | colorTargetInfo.texture = swapchainTexture; 218 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 219 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 220 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 221 | 222 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 223 | SDL_BindGPUGraphicsPipeline(renderPass, Pipelines[CurrentMode]); 224 | SDL_SetGPUViewport(renderPass, &(SDL_GPUViewport){ 0, 0, 320, 480 }); 225 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBufferCW, .offset = 0 }, 1); 226 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 227 | SDL_SetGPUViewport(renderPass, &(SDL_GPUViewport){ 320, 0, 320, 480 }); 228 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBufferCCW, .offset = 0 }, 1); 229 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 230 | SDL_EndGPURenderPass(renderPass); 231 | } 232 | 233 | SDL_SubmitGPUCommandBuffer(cmdbuf); 234 | 235 | return 0; 236 | } 237 | 238 | static void Quit(Context* context) 239 | { 240 | for (int i = 0; i < SDL_arraysize(Pipelines); i += 1) 241 | { 242 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipelines[i]); 243 | } 244 | 245 | SDL_ReleaseGPUBuffer(context->Device, VertexBufferCW); 246 | SDL_ReleaseGPUBuffer(context->Device, VertexBufferCCW); 247 | 248 | CurrentMode = 0; 249 | 250 | CommonQuit(context); 251 | } 252 | 253 | Example CullMode_Example = { "CullMode", Init, Update, Draw, Quit }; 254 | -------------------------------------------------------------------------------- /Examples/DrawIndirect.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* Pipeline; 4 | static SDL_GPUBuffer* VertexBuffer; 5 | static SDL_GPUBuffer* IndexBuffer; 6 | static SDL_GPUBuffer* DrawBuffer; 7 | 8 | static int Init(Context* context) 9 | { 10 | int result = CommonInit(context, 0); 11 | if (result < 0) 12 | { 13 | return result; 14 | } 15 | 16 | // Create the shaders 17 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "PositionColor.vert", 0, 0, 0, 0); 18 | if (vertexShader == NULL) 19 | { 20 | SDL_Log("Failed to create vertex shader!"); 21 | return -1; 22 | } 23 | 24 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 25 | if (fragmentShader == NULL) 26 | { 27 | SDL_Log("Failed to create fragment shader!"); 28 | return -1; 29 | } 30 | 31 | // Create the pipeline 32 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 33 | .target_info = { 34 | .num_color_targets = 1, 35 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 36 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 37 | }}, 38 | }, 39 | // This is set up to match the vertex shader layout! 40 | .vertex_input_state = (SDL_GPUVertexInputState){ 41 | .num_vertex_buffers = 1, 42 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 43 | .slot = 0, 44 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 45 | .instance_step_rate = 0, 46 | .pitch = sizeof(PositionColorVertex) 47 | }}, 48 | .num_vertex_attributes = 2, 49 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 50 | .buffer_slot = 0, 51 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 52 | .location = 0, 53 | .offset = 0 54 | }, { 55 | .buffer_slot = 0, 56 | .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, 57 | .location = 1, 58 | .offset = sizeof(float) * 3 59 | }} 60 | }, 61 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 62 | .vertex_shader = vertexShader, 63 | .fragment_shader = fragmentShader 64 | }; 65 | 66 | Pipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 67 | if (Pipeline == NULL) 68 | { 69 | SDL_Log("Failed to create pipeline!"); 70 | return -1; 71 | } 72 | 73 | SDL_ReleaseGPUShader(context->Device, vertexShader); 74 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 75 | 76 | // Create the buffers 77 | const Uint32 vertexBufferSize = sizeof(PositionColorVertex) * 10; 78 | VertexBuffer = SDL_CreateGPUBuffer( 79 | context->Device, 80 | &(SDL_GPUBufferCreateInfo) { 81 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 82 | .size = vertexBufferSize 83 | } 84 | ); 85 | 86 | const Uint32 indexBufferSize = sizeof(Uint16) * 6; 87 | IndexBuffer = SDL_CreateGPUBuffer( 88 | context->Device, 89 | &(SDL_GPUBufferCreateInfo) { 90 | .usage = SDL_GPU_BUFFERUSAGE_INDEX, 91 | .size = indexBufferSize 92 | } 93 | ); 94 | 95 | const Uint32 drawBufferSize = (sizeof(SDL_GPUIndexedIndirectDrawCommand) * 1) + (sizeof(SDL_GPUIndirectDrawCommand) * 2); 96 | DrawBuffer = SDL_CreateGPUBuffer( 97 | context->Device, 98 | &(SDL_GPUBufferCreateInfo) { 99 | .usage = SDL_GPU_BUFFERUSAGE_INDIRECT, 100 | .size = drawBufferSize 101 | } 102 | ); 103 | 104 | // Set the buffer data 105 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 106 | context->Device, 107 | &(SDL_GPUTransferBufferCreateInfo) { 108 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 109 | .size = vertexBufferSize + indexBufferSize + drawBufferSize 110 | } 111 | ); 112 | 113 | PositionColorVertex* transferData = SDL_MapGPUTransferBuffer( 114 | context->Device, 115 | transferBuffer, 116 | false 117 | ); 118 | 119 | transferData[0] = (PositionColorVertex) { -1, -1, 0, 255, 0, 0, 255 }; 120 | transferData[1] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 121 | transferData[2] = (PositionColorVertex) { 1, 1, 0, 0, 0, 255, 255 }; 122 | transferData[3] = (PositionColorVertex) { -1, 1, 0, 255, 255, 255, 255 }; 123 | 124 | transferData[4] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 125 | transferData[5] = (PositionColorVertex) { 0, -1, 0, 0, 0, 255, 255 }; 126 | transferData[6] = (PositionColorVertex) { 0.5f, 1, 0, 255, 0, 0, 255 }; 127 | transferData[7] = (PositionColorVertex) { -1, -1, 0, 0, 255, 0, 255 }; 128 | transferData[8] = (PositionColorVertex) { 0, -1, 0, 0, 0, 255, 255 }; 129 | transferData[9] = (PositionColorVertex) { -0.5f, 1, 0, 255, 0, 0, 255 }; 130 | 131 | Uint16* indexData = (Uint16*) &transferData[10]; 132 | indexData[0] = 0; 133 | indexData[1] = 1; 134 | indexData[2] = 2; 135 | indexData[3] = 0; 136 | indexData[4] = 2; 137 | indexData[5] = 3; 138 | 139 | SDL_GPUIndexedIndirectDrawCommand* indexedDrawCommand = (SDL_GPUIndexedIndirectDrawCommand*) &indexData[6]; 140 | indexedDrawCommand[0] = (SDL_GPUIndexedIndirectDrawCommand) { 6, 1, 0, 0, 0 }; 141 | 142 | SDL_GPUIndirectDrawCommand* drawCommands = (SDL_GPUIndirectDrawCommand*) &indexedDrawCommand[1]; 143 | drawCommands[0] = (SDL_GPUIndirectDrawCommand) { 3, 1, 4, 0 }; 144 | drawCommands[1] = (SDL_GPUIndirectDrawCommand) { 3, 1, 7, 0 }; 145 | 146 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 147 | 148 | // Upload the transfer data to the GPU buffers 149 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 150 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 151 | 152 | SDL_UploadToGPUBuffer( 153 | copyPass, 154 | &(SDL_GPUTransferBufferLocation) { 155 | .transfer_buffer = transferBuffer, 156 | .offset = 0 157 | }, 158 | &(SDL_GPUBufferRegion) { 159 | .buffer = VertexBuffer, 160 | .offset = 0, 161 | .size = vertexBufferSize 162 | }, 163 | false 164 | ); 165 | 166 | SDL_UploadToGPUBuffer( 167 | copyPass, 168 | &(SDL_GPUTransferBufferLocation) { 169 | .transfer_buffer = transferBuffer, 170 | .offset = vertexBufferSize 171 | }, 172 | &(SDL_GPUBufferRegion) { 173 | .buffer = IndexBuffer, 174 | .offset = 0, 175 | .size = indexBufferSize 176 | }, 177 | false 178 | ); 179 | 180 | SDL_UploadToGPUBuffer( 181 | copyPass, 182 | &(SDL_GPUTransferBufferLocation) { 183 | .transfer_buffer = transferBuffer, 184 | .offset = vertexBufferSize + indexBufferSize 185 | }, 186 | &(SDL_GPUBufferRegion) { 187 | .buffer = DrawBuffer, 188 | .offset = 0, 189 | .size = drawBufferSize 190 | }, 191 | false 192 | ); 193 | 194 | SDL_EndGPUCopyPass(copyPass); 195 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 196 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 197 | 198 | return 0; 199 | } 200 | 201 | static int Update(Context* context) 202 | { 203 | return 0; 204 | } 205 | 206 | static int Draw(Context* context) 207 | { 208 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 209 | if (cmdbuf == NULL) 210 | { 211 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 212 | return -1; 213 | } 214 | 215 | SDL_GPUTexture* swapchainTexture; 216 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 217 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 218 | return -1; 219 | } 220 | 221 | if (swapchainTexture != NULL) 222 | { 223 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 224 | colorTargetInfo.texture = swapchainTexture; 225 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 226 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 227 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 228 | 229 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 230 | 231 | SDL_BindGPUGraphicsPipeline(renderPass, Pipeline); 232 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBuffer, .offset = 0 }, 1); 233 | SDL_BindGPUIndexBuffer(renderPass, &(SDL_GPUBufferBinding) {.buffer = IndexBuffer }, SDL_GPU_INDEXELEMENTSIZE_16BIT); 234 | SDL_DrawGPUIndexedPrimitivesIndirect(renderPass, DrawBuffer, 0, 1); 235 | SDL_DrawGPUPrimitivesIndirect(renderPass, DrawBuffer, sizeof(SDL_GPUIndexedIndirectDrawCommand), 2); 236 | 237 | SDL_EndGPURenderPass(renderPass); 238 | } 239 | 240 | SDL_SubmitGPUCommandBuffer(cmdbuf); 241 | 242 | return 0; 243 | } 244 | 245 | static void Quit(Context* context) 246 | { 247 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipeline); 248 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 249 | SDL_ReleaseGPUBuffer(context->Device, IndexBuffer); 250 | SDL_ReleaseGPUBuffer(context->Device, DrawBuffer); 251 | 252 | CommonQuit(context); 253 | } 254 | 255 | Example DrawIndirect_Example = { "DrawIndirect", Init, Update, Draw, Quit }; 256 | -------------------------------------------------------------------------------- /Examples/CustomSampling.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* Pipeline; 4 | static SDL_GPUBuffer* VertexBuffer; 5 | static SDL_GPUBuffer* IndexBuffer; 6 | static SDL_GPUTexture* Texture; 7 | 8 | static int SamplerMode; 9 | 10 | static int Init(Context* context) 11 | { 12 | int result = CommonInit(context, 0); 13 | if (result < 0) 14 | { 15 | return result; 16 | } 17 | 18 | // Create the shaders 19 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "TexturedQuad.vert", 0, 0, 0, 0); 20 | if (vertexShader == NULL) 21 | { 22 | SDL_Log("Failed to create vertex shader!"); 23 | return -1; 24 | } 25 | 26 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "CustomSampling.frag", 0, 1, 0, 1); 27 | if (fragmentShader == NULL) 28 | { 29 | SDL_Log("Failed to create fragment shader!"); 30 | return -1; 31 | } 32 | 33 | // Load the image 34 | SDL_Surface *imageData = LoadImage("ravioli.bmp", 4); 35 | if (imageData == NULL) 36 | { 37 | SDL_Log("Could not load image data!"); 38 | return -1; 39 | } 40 | 41 | // Create the pipeline 42 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 43 | .target_info = { 44 | .num_color_targets = 1, 45 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 46 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 47 | }}, 48 | }, 49 | .vertex_input_state = (SDL_GPUVertexInputState){ 50 | .num_vertex_buffers = 1, 51 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 52 | .slot = 0, 53 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 54 | .instance_step_rate = 0, 55 | .pitch = sizeof(PositionTextureVertex) 56 | }}, 57 | .num_vertex_attributes = 2, 58 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 59 | .buffer_slot = 0, 60 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 61 | .location = 0, 62 | .offset = 0 63 | }, { 64 | .buffer_slot = 0, 65 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, 66 | .location = 1, 67 | .offset = sizeof(float) * 3 68 | }} 69 | }, 70 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 71 | .vertex_shader = vertexShader, 72 | .fragment_shader = fragmentShader 73 | }; 74 | 75 | Pipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 76 | if (Pipeline == NULL) 77 | { 78 | SDL_Log("Failed to create pipeline!"); 79 | return -1; 80 | } 81 | 82 | SDL_ReleaseGPUShader(context->Device, vertexShader); 83 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 84 | 85 | // Create the GPU resources 86 | VertexBuffer = SDL_CreateGPUBuffer( 87 | context->Device, 88 | &(SDL_GPUBufferCreateInfo) { 89 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 90 | .size = sizeof(PositionTextureVertex) * 4 91 | } 92 | ); 93 | 94 | IndexBuffer = SDL_CreateGPUBuffer( 95 | context->Device, 96 | &(SDL_GPUBufferCreateInfo) { 97 | .usage = SDL_GPU_BUFFERUSAGE_INDEX, 98 | .size = sizeof(Uint16) * 6 99 | } 100 | ); 101 | 102 | Texture = SDL_CreateGPUTexture(context->Device, &(SDL_GPUTextureCreateInfo){ 103 | .type = SDL_GPU_TEXTURETYPE_2D, 104 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 105 | .width = imageData->w, 106 | .height = imageData->h, 107 | .layer_count_or_depth = 1, 108 | .num_levels = 1, 109 | .usage = SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ 110 | }); 111 | 112 | // Set up buffer data 113 | SDL_GPUTransferBuffer* bufferTransferBuffer = SDL_CreateGPUTransferBuffer( 114 | context->Device, 115 | &(SDL_GPUTransferBufferCreateInfo) { 116 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 117 | .size = (sizeof(PositionTextureVertex) * 4) + (sizeof(Uint16) * 6) 118 | } 119 | ); 120 | 121 | PositionTextureVertex* transferData = SDL_MapGPUTransferBuffer( 122 | context->Device, 123 | bufferTransferBuffer, 124 | false 125 | ); 126 | 127 | transferData[0] = (PositionTextureVertex) { -1, 1, 0, 0, 0 }; 128 | transferData[1] = (PositionTextureVertex) { 1, 1, 0, 1, 0 }; 129 | transferData[2] = (PositionTextureVertex) { 1, -1, 0, 1, 1 }; 130 | transferData[3] = (PositionTextureVertex) { -1, -1, 0, 0, 1 }; 131 | 132 | Uint16* indexData = (Uint16*) &transferData[4]; 133 | indexData[0] = 0; 134 | indexData[1] = 1; 135 | indexData[2] = 2; 136 | indexData[3] = 0; 137 | indexData[4] = 2; 138 | indexData[5] = 3; 139 | 140 | SDL_UnmapGPUTransferBuffer(context->Device, bufferTransferBuffer); 141 | 142 | // Set up texture data 143 | SDL_GPUTransferBuffer* textureTransferBuffer = SDL_CreateGPUTransferBuffer( 144 | context->Device, 145 | &(SDL_GPUTransferBufferCreateInfo) { 146 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 147 | .size = imageData->w * imageData->h * 4 148 | } 149 | ); 150 | 151 | Uint8* textureTransferPtr = SDL_MapGPUTransferBuffer( 152 | context->Device, 153 | textureTransferBuffer, 154 | false 155 | ); 156 | SDL_memcpy(textureTransferPtr, imageData->pixels, imageData->w* imageData->h * 4); 157 | SDL_UnmapGPUTransferBuffer(context->Device, textureTransferBuffer); 158 | 159 | // Upload the transfer data to the GPU resources 160 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 161 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 162 | 163 | SDL_UploadToGPUBuffer( 164 | copyPass, 165 | &(SDL_GPUTransferBufferLocation) { 166 | .transfer_buffer = bufferTransferBuffer, 167 | .offset = 0 168 | }, 169 | &(SDL_GPUBufferRegion) { 170 | .buffer = VertexBuffer, 171 | .offset = 0, 172 | .size = sizeof(PositionTextureVertex) * 4 173 | }, 174 | false 175 | ); 176 | 177 | SDL_UploadToGPUBuffer( 178 | copyPass, 179 | &(SDL_GPUTransferBufferLocation) { 180 | .transfer_buffer = bufferTransferBuffer, 181 | .offset = sizeof(PositionTextureVertex) * 4 182 | }, 183 | &(SDL_GPUBufferRegion) { 184 | .buffer = IndexBuffer, 185 | .offset = 0, 186 | .size = sizeof(Uint16) * 6 187 | }, 188 | false 189 | ); 190 | 191 | SDL_UploadToGPUTexture( 192 | copyPass, 193 | &(SDL_GPUTextureTransferInfo) { 194 | .transfer_buffer = textureTransferBuffer, 195 | .offset = 0, /* Zeroes out the rest */ 196 | }, 197 | &(SDL_GPUTextureRegion){ 198 | .texture = Texture, 199 | .w = imageData->w, 200 | .h = imageData->h, 201 | .d = 1 202 | }, 203 | false 204 | ); 205 | 206 | SDL_DestroySurface(imageData); 207 | SDL_EndGPUCopyPass(copyPass); 208 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 209 | SDL_ReleaseGPUTransferBuffer(context->Device, bufferTransferBuffer); 210 | SDL_ReleaseGPUTransferBuffer(context->Device, textureTransferBuffer); 211 | 212 | SDL_Log("Press Left/Right to switch sampler modes"); 213 | SDL_Log("Setting sampler mode to: %d", SamplerMode); 214 | 215 | return 0; 216 | } 217 | 218 | static int Update(Context* context) 219 | { 220 | if (context->LeftPressed || context->RightPressed) 221 | { 222 | SamplerMode = !SamplerMode; 223 | SDL_Log("Setting sampler mode to: %d", SamplerMode); 224 | } 225 | 226 | return 0; 227 | } 228 | 229 | static int Draw(Context* context) 230 | { 231 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 232 | if (cmdbuf == NULL) 233 | { 234 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 235 | return -1; 236 | } 237 | 238 | SDL_GPUTexture* swapchainTexture; 239 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 240 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 241 | return -1; 242 | } 243 | 244 | if (swapchainTexture != NULL) 245 | { 246 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 247 | colorTargetInfo.texture = swapchainTexture; 248 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 249 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 250 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 251 | 252 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); 253 | 254 | SDL_BindGPUGraphicsPipeline(renderPass, Pipeline); 255 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){ .buffer = VertexBuffer, .offset = 0 }, 1); 256 | SDL_BindGPUIndexBuffer(renderPass, &(SDL_GPUBufferBinding){ .buffer = IndexBuffer, .offset = 0 }, SDL_GPU_INDEXELEMENTSIZE_16BIT); 257 | SDL_BindGPUFragmentStorageTextures(renderPass, 0, &Texture, 1); 258 | SDL_PushGPUFragmentUniformData(cmdbuf, 0, &SamplerMode, sizeof(SamplerMode)); 259 | SDL_DrawGPUIndexedPrimitives(renderPass, 6, 1, 0, 0, 0); 260 | 261 | SDL_EndGPURenderPass(renderPass); 262 | } 263 | 264 | SDL_SubmitGPUCommandBuffer(cmdbuf); 265 | 266 | return 0; 267 | } 268 | 269 | static void Quit(Context* context) 270 | { 271 | SDL_ReleaseGPUGraphicsPipeline(context->Device, Pipeline); 272 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 273 | SDL_ReleaseGPUBuffer(context->Device, IndexBuffer); 274 | SDL_ReleaseGPUTexture(context->Device, Texture); 275 | 276 | SamplerMode = 0; 277 | 278 | CommonQuit(context); 279 | } 280 | 281 | Example CustomSampling_Example = { "CustomSampling", Init, Update, Draw, Quit }; 282 | -------------------------------------------------------------------------------- /Examples/PullSpriteBatch.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* RenderPipeline; 4 | static SDL_GPUSampler* Sampler; 5 | static SDL_GPUTexture* Texture; 6 | static SDL_GPUTransferBuffer* SpriteDataTransferBuffer; 7 | static SDL_GPUBuffer* SpriteDataBuffer; 8 | 9 | typedef struct SpriteInstance 10 | { 11 | float x, y, z; 12 | float rotation; 13 | float w, h, padding_a, padding_b; 14 | float tex_u, tex_v, tex_w, tex_h; 15 | float r, g, b, a; 16 | } SpriteInstance; 17 | 18 | static const Uint32 SPRITE_COUNT = 8192; 19 | 20 | static int Init(Context* context) 21 | { 22 | int result = CommonInit(context, 0); 23 | if (result < 0) 24 | { 25 | return result; 26 | } 27 | 28 | SDL_GPUPresentMode presentMode = SDL_GPU_PRESENTMODE_VSYNC; 29 | if (SDL_WindowSupportsGPUPresentMode( 30 | context->Device, 31 | context->Window, 32 | SDL_GPU_PRESENTMODE_IMMEDIATE 33 | )) { 34 | presentMode = SDL_GPU_PRESENTMODE_IMMEDIATE; 35 | } 36 | else if (SDL_WindowSupportsGPUPresentMode( 37 | context->Device, 38 | context->Window, 39 | SDL_GPU_PRESENTMODE_MAILBOX 40 | )) { 41 | presentMode = SDL_GPU_PRESENTMODE_MAILBOX; 42 | } 43 | 44 | SDL_SetGPUSwapchainParameters( 45 | context->Device, 46 | context->Window, 47 | SDL_GPU_SWAPCHAINCOMPOSITION_SDR, 48 | presentMode 49 | ); 50 | 51 | SDL_srand(0); 52 | 53 | // Create the shaders 54 | SDL_GPUShader* vertShader = LoadShader( 55 | context->Device, 56 | "PullSpriteBatch.vert", 57 | 0, 58 | 1, 59 | 1, 60 | 0 61 | ); 62 | 63 | SDL_GPUShader* fragShader = LoadShader( 64 | context->Device, 65 | "TexturedQuadColor.frag", 66 | 1, 67 | 0, 68 | 0, 69 | 0 70 | ); 71 | 72 | // Create the sprite render pipeline 73 | RenderPipeline = SDL_CreateGPUGraphicsPipeline( 74 | context->Device, 75 | &(SDL_GPUGraphicsPipelineCreateInfo){ 76 | .target_info = (SDL_GPUGraphicsPipelineTargetInfo){ 77 | .num_color_targets = 1, 78 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 79 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window), 80 | .blend_state = { 81 | .enable_blend = true, 82 | .color_blend_op = SDL_GPU_BLENDOP_ADD, 83 | .alpha_blend_op = SDL_GPU_BLENDOP_ADD, 84 | .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA, 85 | .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 86 | .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA, 87 | .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 88 | } 89 | }} 90 | }, 91 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 92 | .vertex_shader = vertShader, 93 | .fragment_shader = fragShader 94 | } 95 | ); 96 | 97 | SDL_ReleaseGPUShader(context->Device, vertShader); 98 | SDL_ReleaseGPUShader(context->Device, fragShader); 99 | 100 | // Load the image data 101 | SDL_Surface *imageData = LoadImage("ravioli_atlas.bmp", 4); 102 | if (imageData == NULL) 103 | { 104 | SDL_Log("Could not load image data!"); 105 | return -1; 106 | } 107 | 108 | SDL_GPUTransferBuffer* textureTransferBuffer = SDL_CreateGPUTransferBuffer( 109 | context->Device, 110 | &(SDL_GPUTransferBufferCreateInfo) { 111 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 112 | .size = imageData->w * imageData->h * 4 113 | } 114 | ); 115 | 116 | Uint8 *textureTransferPtr = SDL_MapGPUTransferBuffer( 117 | context->Device, 118 | textureTransferBuffer, 119 | false 120 | ); 121 | SDL_memcpy(textureTransferPtr, imageData->pixels, imageData->w * imageData->h * 4); 122 | SDL_UnmapGPUTransferBuffer(context->Device, textureTransferBuffer); 123 | 124 | // Create the GPU resources 125 | Texture = SDL_CreateGPUTexture( 126 | context->Device, 127 | &(SDL_GPUTextureCreateInfo){ 128 | .type = SDL_GPU_TEXTURETYPE_2D, 129 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 130 | .width = imageData->w, 131 | .height = imageData->h, 132 | .layer_count_or_depth = 1, 133 | .num_levels = 1, 134 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER 135 | } 136 | ); 137 | 138 | Sampler = SDL_CreateGPUSampler( 139 | context->Device, 140 | &(SDL_GPUSamplerCreateInfo){ 141 | .min_filter = SDL_GPU_FILTER_NEAREST, 142 | .mag_filter = SDL_GPU_FILTER_NEAREST, 143 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 144 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 145 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 146 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE 147 | } 148 | ); 149 | 150 | SpriteDataTransferBuffer = SDL_CreateGPUTransferBuffer( 151 | context->Device, 152 | &(SDL_GPUTransferBufferCreateInfo) { 153 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 154 | .size = SPRITE_COUNT * sizeof(SpriteInstance) 155 | } 156 | ); 157 | 158 | SpriteDataBuffer = SDL_CreateGPUBuffer( 159 | context->Device, 160 | &(SDL_GPUBufferCreateInfo) { 161 | .usage = SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ, 162 | .size = SPRITE_COUNT * sizeof(SpriteInstance) 163 | } 164 | ); 165 | 166 | // Transfer the up-front data 167 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 168 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 169 | 170 | SDL_UploadToGPUTexture( 171 | copyPass, 172 | &(SDL_GPUTextureTransferInfo) { 173 | .transfer_buffer = textureTransferBuffer, 174 | .offset = 0, /* Zeroes out the rest */ 175 | }, 176 | &(SDL_GPUTextureRegion){ 177 | .texture = Texture, 178 | .w = imageData->w, 179 | .h = imageData->h, 180 | .d = 1 181 | }, 182 | false 183 | ); 184 | 185 | SDL_EndGPUCopyPass(copyPass); 186 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 187 | 188 | SDL_DestroySurface(imageData); 189 | SDL_ReleaseGPUTransferBuffer(context->Device, textureTransferBuffer); 190 | 191 | return 0; 192 | } 193 | 194 | static int Update(Context* context) 195 | { 196 | return 0; 197 | } 198 | 199 | static float uCoords[4] = { 0.0f, 0.5f, 0.0f, 0.5f }; 200 | static float vCoords[4] = { 0.0f, 0.0f, 0.5f, 0.5f }; 201 | 202 | static int Draw(Context* context) 203 | { 204 | Matrix4x4 cameraMatrix = Matrix4x4_CreateOrthographicOffCenter( 205 | 0, 206 | 640, 207 | 480, 208 | 0, 209 | 0, 210 | -1 211 | ); 212 | 213 | SDL_GPUCommandBuffer* cmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 214 | if (cmdBuf == NULL) 215 | { 216 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 217 | return -1; 218 | } 219 | 220 | SDL_GPUTexture* swapchainTexture; 221 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdBuf, context->Window, &swapchainTexture, NULL, NULL)) { 222 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 223 | return -1; 224 | } 225 | 226 | if (swapchainTexture != NULL) 227 | { 228 | // Build sprite instance transfer 229 | SpriteInstance* dataPtr = SDL_MapGPUTransferBuffer( 230 | context->Device, 231 | SpriteDataTransferBuffer, 232 | true 233 | ); 234 | 235 | for (Uint32 i = 0; i < SPRITE_COUNT; i += 1) 236 | { 237 | Sint32 ravioli = SDL_rand(4); 238 | dataPtr[i].x = (float)(SDL_rand(640)); 239 | dataPtr[i].y = (float)(SDL_rand(480)); 240 | dataPtr[i].z = 0; 241 | dataPtr[i].rotation = SDL_randf() * SDL_PI_F * 2; 242 | dataPtr[i].w = 32; 243 | dataPtr[i].h = 32; 244 | dataPtr[i].tex_u = uCoords[ravioli]; 245 | dataPtr[i].tex_v = vCoords[ravioli]; 246 | dataPtr[i].tex_w = 0.5f; 247 | dataPtr[i].tex_h = 0.5f; 248 | dataPtr[i].r = 1.0f; 249 | dataPtr[i].g = 1.0f; 250 | dataPtr[i].b = 1.0f; 251 | dataPtr[i].a = 1.0f; 252 | } 253 | 254 | SDL_UnmapGPUTransferBuffer(context->Device, SpriteDataTransferBuffer); 255 | 256 | // Upload instance data 257 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdBuf); 258 | SDL_UploadToGPUBuffer( 259 | copyPass, 260 | &(SDL_GPUTransferBufferLocation) { 261 | .transfer_buffer = SpriteDataTransferBuffer, 262 | .offset = 0 263 | }, 264 | &(SDL_GPUBufferRegion) { 265 | .buffer = SpriteDataBuffer, 266 | .offset = 0, 267 | .size = SPRITE_COUNT * sizeof(SpriteInstance) 268 | }, 269 | true 270 | ); 271 | SDL_EndGPUCopyPass(copyPass); 272 | 273 | // Render sprites 274 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass( 275 | cmdBuf, 276 | &(SDL_GPUColorTargetInfo){ 277 | .texture = swapchainTexture, 278 | .cycle = false, 279 | .load_op = SDL_GPU_LOADOP_CLEAR, 280 | .store_op = SDL_GPU_STOREOP_STORE, 281 | .clear_color = { 0, 0, 0, 1 } 282 | }, 283 | 1, 284 | NULL 285 | ); 286 | 287 | SDL_BindGPUGraphicsPipeline(renderPass, RenderPipeline); 288 | SDL_BindGPUVertexStorageBuffers( 289 | renderPass, 290 | 0, 291 | &SpriteDataBuffer, 292 | 1 293 | ); 294 | SDL_BindGPUFragmentSamplers( 295 | renderPass, 296 | 0, 297 | &(SDL_GPUTextureSamplerBinding){ 298 | .texture = Texture, 299 | .sampler = Sampler 300 | }, 301 | 1 302 | ); 303 | SDL_PushGPUVertexUniformData( 304 | cmdBuf, 305 | 0, 306 | &cameraMatrix, 307 | sizeof(Matrix4x4) 308 | ); 309 | SDL_DrawGPUPrimitives( 310 | renderPass, 311 | SPRITE_COUNT * 6, 312 | 1, 313 | 0, 314 | 0 315 | ); 316 | 317 | SDL_EndGPURenderPass(renderPass); 318 | } 319 | 320 | SDL_SubmitGPUCommandBuffer(cmdBuf); 321 | 322 | return 0; 323 | } 324 | 325 | static void Quit(Context* context) 326 | { 327 | SDL_ReleaseGPUGraphicsPipeline(context->Device, RenderPipeline); 328 | SDL_ReleaseGPUSampler(context->Device, Sampler); 329 | SDL_ReleaseGPUTexture(context->Device, Texture); 330 | SDL_ReleaseGPUTransferBuffer(context->Device, SpriteDataTransferBuffer); 331 | SDL_ReleaseGPUBuffer(context->Device, SpriteDataBuffer); 332 | 333 | CommonQuit(context); 334 | } 335 | 336 | Example PullSpriteBatch_Example = { "PullSpriteBatch", Init, Update, Draw, Quit }; 337 | -------------------------------------------------------------------------------- /Examples/ComputeSampler.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static const char* SamplerNames[] = 4 | { 5 | "PointClamp", 6 | "PointWrap", 7 | "LinearClamp", 8 | "LinearWrap", 9 | "AnisotropicClamp", 10 | "AnisotropicWrap", 11 | }; 12 | 13 | static SDL_GPUComputePipeline* Pipeline; 14 | static SDL_GPUTexture* Texture; 15 | static SDL_GPUTexture* WriteTexture; 16 | static SDL_GPUSampler* Samplers[SDL_arraysize(SamplerNames)]; 17 | 18 | static int CurrentSamplerIndex; 19 | 20 | static int Init(Context* context) 21 | { 22 | int result = CommonInit(context, 0); 23 | if (result < 0) 24 | { 25 | return result; 26 | } 27 | 28 | // Load the image 29 | SDL_Surface *imageData = LoadImage("ravioli.bmp", 4); 30 | if (imageData == NULL) 31 | { 32 | SDL_Log("Could not load image data!"); 33 | return -1; 34 | } 35 | 36 | Texture = SDL_CreateGPUTexture(context->Device, &(SDL_GPUTextureCreateInfo){ 37 | .type = SDL_GPU_TEXTURETYPE_2D, 38 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 39 | .width = imageData->w, 40 | .height = imageData->h, 41 | .layer_count_or_depth = 1, 42 | .num_levels = 1, 43 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER 44 | }); 45 | SDL_SetGPUTextureName( 46 | context->Device, 47 | Texture, 48 | "Ravioli Texture 🖼️" 49 | ); 50 | 51 | WriteTexture = SDL_CreateGPUTexture(context->Device, &(SDL_GPUTextureCreateInfo){ 52 | .type = SDL_GPU_TEXTURETYPE_2D, 53 | .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, 54 | .width = 640, 55 | .height = 480, 56 | .layer_count_or_depth =1, 57 | .num_levels = 1, 58 | .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE 59 | }); 60 | 61 | Pipeline = CreateComputePipelineFromShader( 62 | context->Device, 63 | "TexturedQuad.comp", 64 | &(SDL_GPUComputePipelineCreateInfo){ 65 | .num_samplers = 1, 66 | .num_readwrite_storage_textures = 1, 67 | .num_uniform_buffers = 1, 68 | .threadcount_x = 8, 69 | .threadcount_y = 8, 70 | .threadcount_z = 1, 71 | } 72 | ); 73 | 74 | // PointClamp 75 | Samplers[0] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 76 | .min_filter = SDL_GPU_FILTER_NEAREST, 77 | .mag_filter = SDL_GPU_FILTER_NEAREST, 78 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 79 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 80 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 81 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 82 | }); 83 | // PointWrap 84 | Samplers[1] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 85 | .min_filter = SDL_GPU_FILTER_NEAREST, 86 | .mag_filter = SDL_GPU_FILTER_NEAREST, 87 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 88 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 89 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 90 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 91 | }); 92 | // LinearClamp 93 | Samplers[2] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 94 | .min_filter = SDL_GPU_FILTER_LINEAR, 95 | .mag_filter = SDL_GPU_FILTER_LINEAR, 96 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 97 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 98 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 99 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 100 | }); 101 | // LinearWrap 102 | Samplers[3] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 103 | .min_filter = SDL_GPU_FILTER_LINEAR, 104 | .mag_filter = SDL_GPU_FILTER_LINEAR, 105 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 106 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 107 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 108 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 109 | }); 110 | // AnisotropicClamp 111 | Samplers[4] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 112 | .min_filter = SDL_GPU_FILTER_LINEAR, 113 | .mag_filter = SDL_GPU_FILTER_LINEAR, 114 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 115 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 116 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 117 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, 118 | .enable_anisotropy = true, 119 | .max_anisotropy = 4 120 | }); 121 | // AnisotropicWrap 122 | Samplers[5] = SDL_CreateGPUSampler(context->Device, &(SDL_GPUSamplerCreateInfo){ 123 | .min_filter = SDL_GPU_FILTER_LINEAR, 124 | .mag_filter = SDL_GPU_FILTER_LINEAR, 125 | .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 126 | .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 127 | .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 128 | .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_REPEAT, 129 | .enable_anisotropy = true, 130 | .max_anisotropy = 4 131 | }); 132 | 133 | // Set up texture data 134 | SDL_GPUTransferBuffer* textureTransferBuffer = SDL_CreateGPUTransferBuffer( 135 | context->Device, 136 | &(SDL_GPUTransferBufferCreateInfo) { 137 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 138 | .size = imageData->w * imageData->h * 4 139 | } 140 | ); 141 | 142 | Uint8* textureTransferPtr = SDL_MapGPUTransferBuffer( 143 | context->Device, 144 | textureTransferBuffer, 145 | false 146 | ); 147 | SDL_memcpy(textureTransferPtr, imageData->pixels, imageData->w * imageData->h * 4); 148 | SDL_UnmapGPUTransferBuffer(context->Device, textureTransferBuffer); 149 | 150 | // Upload the transfer data to the GPU resources 151 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 152 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 153 | 154 | SDL_UploadToGPUTexture( 155 | copyPass, 156 | &(SDL_GPUTextureTransferInfo) { 157 | .transfer_buffer = textureTransferBuffer, 158 | .offset = 0, /* Zeros out the rest */ 159 | }, 160 | &(SDL_GPUTextureRegion){ 161 | .texture = Texture, 162 | .w = imageData->w, 163 | .h = imageData->h, 164 | .d = 1 165 | }, 166 | false 167 | ); 168 | 169 | SDL_EndGPUCopyPass(copyPass); 170 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 171 | 172 | SDL_ReleaseGPUTransferBuffer(context->Device, textureTransferBuffer); 173 | SDL_DestroySurface(imageData); 174 | 175 | // Finally, print instructions! 176 | SDL_Log("Press Left/Right to switch between sampler states"); 177 | SDL_Log("Setting sampler state to: %s", SamplerNames[0]); 178 | 179 | return 0; 180 | } 181 | 182 | static int Update(Context* context) 183 | { 184 | if (context->LeftPressed) 185 | { 186 | CurrentSamplerIndex -= 1; 187 | if (CurrentSamplerIndex < 0) 188 | { 189 | CurrentSamplerIndex = SDL_arraysize(Samplers) - 1; 190 | } 191 | SDL_Log("Setting sampler state to: %s", SamplerNames[CurrentSamplerIndex]); 192 | } 193 | 194 | if (context->RightPressed) 195 | { 196 | CurrentSamplerIndex = (CurrentSamplerIndex + 1) % SDL_arraysize(Samplers); 197 | SDL_Log("Setting sampler state to: %s", SamplerNames[CurrentSamplerIndex]); 198 | } 199 | 200 | return 0; 201 | } 202 | 203 | static int Draw(Context* context) 204 | { 205 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 206 | if (cmdbuf == NULL) 207 | { 208 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 209 | return -1; 210 | } 211 | 212 | SDL_GPUTexture* swapchainTexture; 213 | Uint32 w, h; 214 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, &w, &h)) { 215 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 216 | return -1; 217 | } 218 | 219 | if (swapchainTexture != NULL) 220 | { 221 | SDL_GPUComputePass *computePass = SDL_BeginGPUComputePass( 222 | cmdbuf, 223 | &(SDL_GPUStorageTextureReadWriteBinding){ 224 | .texture = WriteTexture, 225 | .layer = 0, 226 | .mip_level = 0, 227 | .cycle = true 228 | }, 229 | 1, 230 | NULL, 231 | 0); 232 | 233 | SDL_BindGPUComputePipeline(computePass, Pipeline); 234 | SDL_BindGPUComputeSamplers( 235 | computePass, 236 | 0, 237 | &(SDL_GPUTextureSamplerBinding){ 238 | .texture = Texture, 239 | .sampler = Samplers[CurrentSamplerIndex] 240 | }, 241 | 1); 242 | float texcoordMultiplier = 0.25f; 243 | SDL_PushGPUComputeUniformData(cmdbuf, 0, &texcoordMultiplier, sizeof(float)); 244 | 245 | SDL_DispatchGPUCompute(computePass, w / 8, h / 8, 1); 246 | SDL_EndGPUComputePass(computePass); 247 | 248 | SDL_BlitGPUTexture( 249 | cmdbuf, 250 | &(SDL_GPUBlitInfo){ 251 | .source.texture = WriteTexture, 252 | .source.w = 640, 253 | .source.h = 480, 254 | .destination.texture = swapchainTexture, 255 | .destination.w = w, 256 | .destination.h = h, 257 | .load_op = SDL_GPU_LOADOP_DONT_CARE, 258 | .filter = SDL_GPU_FILTER_NEAREST 259 | } 260 | ); 261 | } 262 | 263 | SDL_SubmitGPUCommandBuffer(cmdbuf); 264 | 265 | return 0; 266 | } 267 | 268 | static void Quit(Context* context) 269 | { 270 | SDL_ReleaseGPUComputePipeline(context->Device, Pipeline); 271 | SDL_ReleaseGPUTexture(context->Device, Texture); 272 | SDL_ReleaseGPUTexture(context->Device, WriteTexture); 273 | 274 | for (int i = 0; i < SDL_arraysize(Samplers); i += 1) 275 | { 276 | SDL_ReleaseGPUSampler(context->Device, Samplers[i]); 277 | } 278 | 279 | CurrentSamplerIndex = 0; 280 | 281 | CommonQuit(context); 282 | } 283 | 284 | Example ComputeSampler_Example = { "ComputeSampler", Init, Update, Draw, Quit }; 285 | -------------------------------------------------------------------------------- /Examples/BasicStencil.c: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | static SDL_GPUGraphicsPipeline* MaskerPipeline; 4 | static SDL_GPUGraphicsPipeline* MaskeePipeline; 5 | static SDL_GPUBuffer* VertexBuffer; 6 | static SDL_GPUTexture* DepthStencilTexture; 7 | 8 | static int Init(Context* context) 9 | { 10 | int result = CommonInit(context, 0); 11 | if (result < 0) 12 | { 13 | return result; 14 | } 15 | 16 | SDL_GPUShader* vertexShader = LoadShader(context->Device, "PositionColor.vert", 0, 0, 0, 0); 17 | if (vertexShader == NULL) 18 | { 19 | SDL_Log("Failed to create vertex shader!"); 20 | return -1; 21 | } 22 | 23 | SDL_GPUShader* fragmentShader = LoadShader(context->Device, "SolidColor.frag", 0, 0, 0, 0); 24 | if (fragmentShader == NULL) 25 | { 26 | SDL_Log("Failed to create fragment shader!"); 27 | return -1; 28 | } 29 | 30 | SDL_GPUTextureFormat depthStencilFormat; 31 | 32 | if (SDL_GPUTextureSupportsFormat( 33 | context->Device, 34 | SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT, 35 | SDL_GPU_TEXTURETYPE_2D, 36 | SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET 37 | )) 38 | { 39 | depthStencilFormat = SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT; 40 | } 41 | else if (SDL_GPUTextureSupportsFormat( 42 | context->Device, 43 | SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT, 44 | SDL_GPU_TEXTURETYPE_2D, 45 | SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET 46 | )) 47 | { 48 | depthStencilFormat = SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT; 49 | } 50 | else 51 | { 52 | SDL_Log("Stencil formats not supported!"); 53 | return -1; 54 | } 55 | 56 | SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { 57 | .target_info = { 58 | .num_color_targets = 1, 59 | .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ 60 | .format = SDL_GetGPUSwapchainTextureFormat(context->Device, context->Window) 61 | }}, 62 | .has_depth_stencil_target = true, 63 | .depth_stencil_format = depthStencilFormat 64 | }, 65 | .depth_stencil_state = (SDL_GPUDepthStencilState){ 66 | .enable_stencil_test = true, 67 | .front_stencil_state = (SDL_GPUStencilOpState){ 68 | .compare_op = SDL_GPU_COMPAREOP_NEVER, 69 | .fail_op = SDL_GPU_STENCILOP_REPLACE, 70 | .pass_op = SDL_GPU_STENCILOP_KEEP, 71 | .depth_fail_op = SDL_GPU_STENCILOP_KEEP, 72 | }, 73 | .back_stencil_state = (SDL_GPUStencilOpState){ 74 | .compare_op = SDL_GPU_COMPAREOP_NEVER, 75 | .fail_op = SDL_GPU_STENCILOP_REPLACE, 76 | .pass_op = SDL_GPU_STENCILOP_KEEP, 77 | .depth_fail_op = SDL_GPU_STENCILOP_KEEP, 78 | }, 79 | .write_mask = 0xFF 80 | }, 81 | .rasterizer_state = (SDL_GPURasterizerState){ 82 | .cull_mode = SDL_GPU_CULLMODE_NONE, 83 | .fill_mode = SDL_GPU_FILLMODE_FILL, 84 | .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE 85 | }, 86 | .vertex_input_state = (SDL_GPUVertexInputState){ 87 | .num_vertex_buffers = 1, 88 | .vertex_buffer_descriptions = (SDL_GPUVertexBufferDescription[]){{ 89 | .slot = 0, 90 | .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, 91 | .instance_step_rate = 0, 92 | .pitch = sizeof(PositionColorVertex) 93 | }}, 94 | .num_vertex_attributes = 2, 95 | .vertex_attributes = (SDL_GPUVertexAttribute[]){{ 96 | .buffer_slot = 0, 97 | .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 98 | .location = 0, 99 | .offset = 0 100 | }, { 101 | .buffer_slot = 0, 102 | .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, 103 | .location = 1, 104 | .offset = sizeof(float) * 3 105 | }} 106 | }, 107 | .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, 108 | .vertex_shader = vertexShader, 109 | .fragment_shader = fragmentShader 110 | }; 111 | 112 | MaskerPipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 113 | if (MaskerPipeline == NULL) 114 | { 115 | SDL_Log("Failed to create masker pipeline!"); 116 | return -1; 117 | } 118 | 119 | pipelineCreateInfo.depth_stencil_state = (SDL_GPUDepthStencilState){ 120 | .enable_stencil_test = true, 121 | .front_stencil_state = (SDL_GPUStencilOpState){ 122 | .compare_op = SDL_GPU_COMPAREOP_EQUAL, 123 | .fail_op = SDL_GPU_STENCILOP_KEEP, 124 | .pass_op = SDL_GPU_STENCILOP_KEEP, 125 | .depth_fail_op = SDL_GPU_STENCILOP_KEEP, 126 | }, 127 | .back_stencil_state = (SDL_GPUStencilOpState){ 128 | .compare_op = SDL_GPU_COMPAREOP_NEVER, 129 | .fail_op = SDL_GPU_STENCILOP_KEEP, 130 | .pass_op = SDL_GPU_STENCILOP_KEEP, 131 | .depth_fail_op = SDL_GPU_STENCILOP_KEEP, 132 | }, 133 | .compare_mask = 0xFF, 134 | .write_mask = 0 135 | }; 136 | 137 | MaskeePipeline = SDL_CreateGPUGraphicsPipeline(context->Device, &pipelineCreateInfo); 138 | if (MaskeePipeline == NULL) 139 | { 140 | SDL_Log("Failed to create maskee pipeline!"); 141 | return -1; 142 | } 143 | 144 | SDL_ReleaseGPUShader(context->Device, vertexShader); 145 | SDL_ReleaseGPUShader(context->Device, fragmentShader); 146 | 147 | VertexBuffer = SDL_CreateGPUBuffer( 148 | context->Device, 149 | &(SDL_GPUBufferCreateInfo) { 150 | .usage = SDL_GPU_BUFFERUSAGE_VERTEX, 151 | .size = sizeof(PositionColorVertex) * 6 152 | } 153 | ); 154 | 155 | int w, h; 156 | SDL_GetWindowSizeInPixels(context->Window, &w, &h); 157 | 158 | DepthStencilTexture = SDL_CreateGPUTexture( 159 | context->Device, 160 | &(SDL_GPUTextureCreateInfo) { 161 | .type = SDL_GPU_TEXTURETYPE_2D, 162 | .width = w, 163 | .height = h, 164 | .layer_count_or_depth = 1, 165 | .num_levels = 1, 166 | .sample_count = SDL_GPU_SAMPLECOUNT_1, 167 | .format = depthStencilFormat, 168 | .usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET 169 | } 170 | ); 171 | 172 | SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer( 173 | context->Device, 174 | &(SDL_GPUTransferBufferCreateInfo) { 175 | .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, 176 | .size = sizeof(PositionColorVertex) * 6 177 | } 178 | ); 179 | 180 | PositionColorVertex* transferData = SDL_MapGPUTransferBuffer( 181 | context->Device, 182 | transferBuffer, 183 | false 184 | ); 185 | 186 | transferData[0] = (PositionColorVertex) { -0.5f, -0.5f, 0, 255, 255, 0, 255 }; 187 | transferData[1] = (PositionColorVertex) { 0.5f, -0.5f, 0, 255, 255, 0, 255 }; 188 | transferData[2] = (PositionColorVertex) { 0, 0.5f, 0, 255, 255, 0, 255 }; 189 | transferData[3] = (PositionColorVertex) { -1, -1, 0, 255, 0, 0, 255 }; 190 | transferData[4] = (PositionColorVertex) { 1, -1, 0, 0, 255, 0, 255 }; 191 | transferData[5] = (PositionColorVertex) { 0, 1, 0, 0, 0, 255, 255 }; 192 | 193 | SDL_UnmapGPUTransferBuffer(context->Device, transferBuffer); 194 | 195 | SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(context->Device); 196 | SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf); 197 | 198 | SDL_UploadToGPUBuffer( 199 | copyPass, 200 | &(SDL_GPUTransferBufferLocation) { 201 | .transfer_buffer = transferBuffer, 202 | .offset = 0 203 | }, 204 | &(SDL_GPUBufferRegion) { 205 | .buffer = VertexBuffer, 206 | .offset = 0, 207 | .size = sizeof(PositionColorVertex) * 6 208 | }, 209 | false 210 | ); 211 | 212 | SDL_EndGPUCopyPass(copyPass); 213 | SDL_SubmitGPUCommandBuffer(uploadCmdBuf); 214 | SDL_ReleaseGPUTransferBuffer(context->Device, transferBuffer); 215 | 216 | return 0; 217 | } 218 | 219 | static int Update(Context* context) 220 | { 221 | return 0; 222 | } 223 | 224 | static int Draw(Context* context) 225 | { 226 | SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(context->Device); 227 | if (cmdbuf == NULL) 228 | { 229 | SDL_Log("AcquireGPUCommandBuffer failed: %s", SDL_GetError()); 230 | return -1; 231 | } 232 | 233 | SDL_GPUTexture* swapchainTexture; 234 | if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, context->Window, &swapchainTexture, NULL, NULL)) { 235 | SDL_Log("WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); 236 | return -1; 237 | } 238 | 239 | if (swapchainTexture != NULL) 240 | { 241 | SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; 242 | colorTargetInfo.texture = swapchainTexture; 243 | colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; 244 | colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 245 | colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; 246 | 247 | SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = { 0 }; 248 | depthStencilTargetInfo.texture = DepthStencilTexture; 249 | depthStencilTargetInfo.cycle = true; 250 | depthStencilTargetInfo.clear_depth = 0; 251 | depthStencilTargetInfo.clear_stencil = 0; 252 | depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; 253 | depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_DONT_CARE; 254 | depthStencilTargetInfo.stencil_load_op = SDL_GPU_LOADOP_CLEAR; 255 | depthStencilTargetInfo.stencil_store_op = SDL_GPU_STOREOP_DONT_CARE; 256 | 257 | SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass( 258 | cmdbuf, 259 | &colorTargetInfo, 260 | 1, 261 | &depthStencilTargetInfo 262 | ); 263 | 264 | SDL_BindGPUVertexBuffers(renderPass, 0, &(SDL_GPUBufferBinding){.buffer = VertexBuffer, .offset = 0 }, 1); 265 | 266 | SDL_SetGPUStencilReference(renderPass, 1); 267 | SDL_BindGPUGraphicsPipeline(renderPass, MaskerPipeline); 268 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); 269 | 270 | SDL_SetGPUStencilReference(renderPass, 0); 271 | SDL_BindGPUGraphicsPipeline(renderPass, MaskeePipeline); 272 | SDL_DrawGPUPrimitives(renderPass, 3, 1, 3, 0); 273 | 274 | SDL_EndGPURenderPass(renderPass); 275 | } 276 | 277 | SDL_SubmitGPUCommandBuffer(cmdbuf); 278 | 279 | return 0; 280 | } 281 | 282 | static void Quit(Context* context) 283 | { 284 | SDL_ReleaseGPUGraphicsPipeline(context->Device, MaskeePipeline); 285 | SDL_ReleaseGPUGraphicsPipeline(context->Device, MaskerPipeline); 286 | 287 | SDL_ReleaseGPUTexture(context->Device, DepthStencilTexture); 288 | SDL_ReleaseGPUBuffer(context->Device, VertexBuffer); 289 | 290 | CommonQuit(context); 291 | } 292 | 293 | Example BasicStencil_Example = { "BasicStencil", Init, Update, Draw, Quit }; 294 | --------------------------------------------------------------------------------