const std = @import("std");
pub const c = @import("c.zig").c;

pub const FColor = extern struct {
    r: f32,
    g: f32,
    b: f32,
    a: f32,
};

pub const PropertiesID = u32;

pub const PixelFormat = enum(c_int) {
    pixelformatYv12 = 0x32315659u, //Planar mode: Y + V + U  (3 planes)
    pixelformatIyuv = 0x56555949u, //Planar mode: Y + U + V  (3 planes)
    pixelformatYuy2 = 0x32595559u, //Packed mode: Y0+U0+Y1+V0 (1 plane)
    pixelformatUyvy = 0x59565955u, //Packed mode: U0+Y0+V0+Y1 (1 plane)
    pixelformatYvyu = 0x55595659u, //Packed mode: Y0+V0+Y1+U0 (1 plane)
    pixelformatNv12 = 0x3231564eu, //Planar mode: Y + U/V interleaved  (2 planes)
    pixelformatNv21 = 0x3132564eu, //Planar mode: Y + V/U interleaved  (2 planes)
    pixelformatP010 = 0x30313050u, //Planar mode: Y + U/V interleaved  (2 planes)
    pixelformatExternalOes = 0x2053454fu, //Android video texture format
    pixelformatMjpg = 0x47504a4du, //Motion JPEG
};

pub const Rect = extern struct {
    x: c_int,
    y: c_int,
    w: c_int,
    h: c_int,
};

pub const Window = opaque {};

pub const FlipMode = enum(c_int) {
    flipNone, //Do not flip
    flipHorizontal, //flip horizontally
    flipVertical, //flip vertically
    flipHorizontalAndVertical = (SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL), //flip horizontally and vertically (not a diagonal flip)
};

pub const GPUDevice = opaque {
    pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void {
        return c.SDL_DestroyGPUDevice(gpudevice);
    }

    pub inline fn getGPUDeviceDriver(gpudevice: *GPUDevice) [*c]const u8 {
        return c.SDL_GetGPUDeviceDriver(gpudevice);
    }

    pub inline fn getGPUShaderFormats(gpudevice: *GPUDevice) GPUShaderFormat {
        return @bitCast(c.SDL_GetGPUShaderFormats(gpudevice));
    }

    pub inline fn getGPUDeviceProperties(gpudevice: *GPUDevice) PropertiesID {
        return c.SDL_GetGPUDeviceProperties(gpudevice);
    }

    pub inline fn createGPUComputePipeline(gpudevice: *GPUDevice, createinfo: *const GPUComputePipelineCreateInfo) ?*GPUComputePipeline {
        return c.SDL_CreateGPUComputePipeline(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUGraphicsPipeline(gpudevice: *GPUDevice, createinfo: *const GPUGraphicsPipelineCreateInfo) ?*GPUGraphicsPipeline {
        return c.SDL_CreateGPUGraphicsPipeline(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUSampler(gpudevice: *GPUDevice, createinfo: *const GPUSamplerCreateInfo) ?*GPUSampler {
        return c.SDL_CreateGPUSampler(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUShader(gpudevice: *GPUDevice, createinfo: *const GPUShaderCreateInfo) ?*GPUShader {
        return c.SDL_CreateGPUShader(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUTexture(gpudevice: *GPUDevice, createinfo: *const GPUTextureCreateInfo) ?*GPUTexture {
        return c.SDL_CreateGPUTexture(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUBuffer(gpudevice: *GPUDevice, createinfo: *const GPUBufferCreateInfo) ?*GPUBuffer {
        return c.SDL_CreateGPUBuffer(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn createGPUTransferBuffer(gpudevice: *GPUDevice, createinfo: *const GPUTransferBufferCreateInfo) ?*GPUTransferBuffer {
        return c.SDL_CreateGPUTransferBuffer(gpudevice, @ptrCast(createinfo));
    }

    pub inline fn setGPUBufferName(gpudevice: *GPUDevice, buffer: ?*GPUBuffer, text: [*c]const u8) void {
        return c.SDL_SetGPUBufferName(gpudevice, buffer, text);
    }

    pub inline fn setGPUTextureName(gpudevice: *GPUDevice, texture: ?*GPUTexture, text: [*c]const u8) void {
        return c.SDL_SetGPUTextureName(gpudevice, texture, text);
    }

    pub inline fn releaseGPUTexture(gpudevice: *GPUDevice, texture: ?*GPUTexture) void {
        return c.SDL_ReleaseGPUTexture(gpudevice, texture);
    }

    pub inline fn releaseGPUSampler(gpudevice: *GPUDevice, sampler: ?*GPUSampler) void {
        return c.SDL_ReleaseGPUSampler(gpudevice, sampler);
    }

    pub inline fn releaseGPUBuffer(gpudevice: *GPUDevice, buffer: ?*GPUBuffer) void {
        return c.SDL_ReleaseGPUBuffer(gpudevice, buffer);
    }

    pub inline fn releaseGPUTransferBuffer(gpudevice: *GPUDevice, transfer_buffer: ?*GPUTransferBuffer) void {
        return c.SDL_ReleaseGPUTransferBuffer(gpudevice, transfer_buffer);
    }

    pub inline fn releaseGPUComputePipeline(gpudevice: *GPUDevice, compute_pipeline: ?*GPUComputePipeline) void {
        return c.SDL_ReleaseGPUComputePipeline(gpudevice, compute_pipeline);
    }

    pub inline fn releaseGPUShader(gpudevice: *GPUDevice, shader: ?*GPUShader) void {
        return c.SDL_ReleaseGPUShader(gpudevice, shader);
    }

    pub inline fn releaseGPUGraphicsPipeline(gpudevice: *GPUDevice, graphics_pipeline: ?*GPUGraphicsPipeline) void {
        return c.SDL_ReleaseGPUGraphicsPipeline(gpudevice, graphics_pipeline);
    }

    pub inline fn acquireGPUCommandBuffer(gpudevice: *GPUDevice) ?*GPUCommandBuffer {
        return c.SDL_AcquireGPUCommandBuffer(gpudevice);
    }

    pub inline fn mapGPUTransferBuffer(gpudevice: *GPUDevice, transfer_buffer: ?*GPUTransferBuffer, cycle: bool) ?*anyopaque {
        return c.SDL_MapGPUTransferBuffer(gpudevice, transfer_buffer, cycle);
    }

    pub inline fn unmapGPUTransferBuffer(gpudevice: *GPUDevice, transfer_buffer: ?*GPUTransferBuffer) void {
        return c.SDL_UnmapGPUTransferBuffer(gpudevice, transfer_buffer);
    }

    pub inline fn windowSupportsGPUSwapchainComposition(gpudevice: *GPUDevice, window: ?*Window, swapchain_composition: GPUSwapchainComposition) bool {
        return c.SDL_WindowSupportsGPUSwapchainComposition(gpudevice, window, swapchain_composition);
    }

    pub inline fn windowSupportsGPUPresentMode(gpudevice: *GPUDevice, window: ?*Window, present_mode: GPUPresentMode) bool {
        return c.SDL_WindowSupportsGPUPresentMode(gpudevice, window, @intFromEnum(present_mode));
    }

    pub inline fn claimWindowForGPUDevice(gpudevice: *GPUDevice, window: ?*Window) bool {
        return c.SDL_ClaimWindowForGPUDevice(gpudevice, window);
    }

    pub inline fn releaseWindowFromGPUDevice(gpudevice: *GPUDevice, window: ?*Window) void {
        return c.SDL_ReleaseWindowFromGPUDevice(gpudevice, window);
    }

    pub inline fn setGPUSwapchainParameters(gpudevice: *GPUDevice, window: ?*Window, swapchain_composition: GPUSwapchainComposition, present_mode: GPUPresentMode) bool {
        return c.SDL_SetGPUSwapchainParameters(gpudevice, window, swapchain_composition, @intFromEnum(present_mode));
    }

    pub inline fn setGPUAllowedFramesInFlight(gpudevice: *GPUDevice, allowed_frames_in_flight: u32) bool {
        return c.SDL_SetGPUAllowedFramesInFlight(gpudevice, allowed_frames_in_flight);
    }

    pub inline fn getGPUSwapchainTextureFormat(gpudevice: *GPUDevice, window: ?*Window) GPUTextureFormat {
        return @bitCast(c.SDL_GetGPUSwapchainTextureFormat(gpudevice, window));
    }

    pub inline fn waitForGPUSwapchain(gpudevice: *GPUDevice, window: ?*Window) bool {
        return c.SDL_WaitForGPUSwapchain(gpudevice, window);
    }

    pub inline fn waitForGPUIdle(gpudevice: *GPUDevice) bool {
        return c.SDL_WaitForGPUIdle(gpudevice);
    }

    pub inline fn waitForGPUFences(gpudevice: *GPUDevice, wait_all: bool, fences: [*c]*const GPUFence, num_fences: u32) bool {
        return c.SDL_WaitForGPUFences(gpudevice, wait_all, fences, num_fences);
    }

    pub inline fn queryGPUFence(gpudevice: *GPUDevice, fence: ?*GPUFence) bool {
        return c.SDL_QueryGPUFence(gpudevice, fence);
    }

    pub inline fn releaseGPUFence(gpudevice: *GPUDevice, fence: ?*GPUFence) void {
        return c.SDL_ReleaseGPUFence(gpudevice, fence);
    }

    pub inline fn gpuTextureSupportsFormat(gpudevice: *GPUDevice, format: GPUTextureFormat, _type: GPUTextureType, usage: GPUTextureUsageFlags) bool {
        return c.SDL_GPUTextureSupportsFormat(gpudevice, @bitCast(format), @intFromEnum(_type), @bitCast(usage));
    }

    pub inline fn gpuTextureSupportsSampleCount(gpudevice: *GPUDevice, format: GPUTextureFormat, sample_count: GPUSampleCount) bool {
        return c.SDL_GPUTextureSupportsSampleCount(gpudevice, @bitCast(format), sample_count);
    }

    pub inline fn gdkSuspendGPU(gpudevice: *GPUDevice) void {
        return c.SDL_GDKSuspendGPU(gpudevice);
    }

    pub inline fn gdkResumeGPU(gpudevice: *GPUDevice) void {
        return c.SDL_GDKResumeGPU(gpudevice);
    }
};

pub const GPUBuffer = opaque {};

pub const GPUTransferBuffer = opaque {};

pub const GPUTexture = opaque {};

pub const GPUSampler = opaque {};

pub const GPUShader = opaque {};

pub const GPUComputePipeline = opaque {};

pub const GPUGraphicsPipeline = opaque {};

pub const GPUCommandBuffer = opaque {
    pub inline fn insertGPUDebugLabel(gpucommandbuffer: *GPUCommandBuffer, text: [*c]const u8) void {
        return c.SDL_InsertGPUDebugLabel(gpucommandbuffer, text);
    }

    pub inline fn pushGPUDebugGroup(gpucommandbuffer: *GPUCommandBuffer, name: [*c]const u8) void {
        return c.SDL_PushGPUDebugGroup(gpucommandbuffer, name);
    }

    pub inline fn popGPUDebugGroup(gpucommandbuffer: *GPUCommandBuffer) void {
        return c.SDL_PopGPUDebugGroup(gpucommandbuffer);
    }

    pub inline fn pushGPUVertexUniformData(gpucommandbuffer: *GPUCommandBuffer, slot_index: u32, data: ?*const anyopaque, length: u32) void {
        return c.SDL_PushGPUVertexUniformData(gpucommandbuffer, slot_index, data, length);
    }

    pub inline fn pushGPUFragmentUniformData(gpucommandbuffer: *GPUCommandBuffer, slot_index: u32, data: ?*const anyopaque, length: u32) void {
        return c.SDL_PushGPUFragmentUniformData(gpucommandbuffer, slot_index, data, length);
    }

    pub inline fn pushGPUComputeUniformData(gpucommandbuffer: *GPUCommandBuffer, slot_index: u32, data: ?*const anyopaque, length: u32) void {
        return c.SDL_PushGPUComputeUniformData(gpucommandbuffer, slot_index, data, length);
    }

    pub inline fn beginGPURenderPass(gpucommandbuffer: *GPUCommandBuffer, color_target_infos: *const GPUColorTargetInfo, num_color_targets: u32, depth_stencil_target_info: *const GPUDepthStencilTargetInfo) ?*GPURenderPass {
        return c.SDL_BeginGPURenderPass(gpucommandbuffer, @ptrCast(color_target_infos), num_color_targets, @ptrCast(depth_stencil_target_info));
    }

    pub inline fn beginGPUComputePass(gpucommandbuffer: *GPUCommandBuffer, storage_texture_bindings: *const GPUStorageTextureReadWriteBinding, num_storage_texture_bindings: u32, storage_buffer_bindings: *const GPUStorageBufferReadWriteBinding, num_storage_buffer_bindings: u32) ?*GPUComputePass {
        return c.SDL_BeginGPUComputePass(gpucommandbuffer, @ptrCast(storage_texture_bindings), num_storage_texture_bindings, @ptrCast(storage_buffer_bindings), num_storage_buffer_bindings);
    }

    pub inline fn beginGPUCopyPass(gpucommandbuffer: *GPUCommandBuffer) ?*GPUCopyPass {
        return c.SDL_BeginGPUCopyPass(gpucommandbuffer);
    }

    pub inline fn generateMipmapsForGPUTexture(gpucommandbuffer: *GPUCommandBuffer, texture: ?*GPUTexture) void {
        return c.SDL_GenerateMipmapsForGPUTexture(gpucommandbuffer, texture);
    }

    pub inline fn blitGPUTexture(gpucommandbuffer: *GPUCommandBuffer, info: *const GPUBlitInfo) void {
        return c.SDL_BlitGPUTexture(gpucommandbuffer, @ptrCast(info));
    }

    pub inline fn acquireGPUSwapchainTexture(gpucommandbuffer: *GPUCommandBuffer, window: ?*Window, swapchain_texture: [*c][*c]GPUTexture, swapchain_texture_width: *u32, swapchain_texture_height: *u32) bool {
        return c.SDL_AcquireGPUSwapchainTexture(gpucommandbuffer, window, swapchain_texture, @ptrCast(swapchain_texture_width), @ptrCast(swapchain_texture_height));
    }

    pub inline fn waitAndAcquireGPUSwapchainTexture(gpucommandbuffer: *GPUCommandBuffer, window: ?*Window, swapchain_texture: [*c][*c]GPUTexture, swapchain_texture_width: *u32, swapchain_texture_height: *u32) bool {
        return c.SDL_WaitAndAcquireGPUSwapchainTexture(gpucommandbuffer, window, swapchain_texture, @ptrCast(swapchain_texture_width), @ptrCast(swapchain_texture_height));
    }

    pub inline fn submitGPUCommandBuffer(gpucommandbuffer: *GPUCommandBuffer) bool {
        return c.SDL_SubmitGPUCommandBuffer(gpucommandbuffer);
    }

    pub inline fn submitGPUCommandBufferAndAcquireFence(gpucommandbuffer: *GPUCommandBuffer) ?*GPUFence {
        return c.SDL_SubmitGPUCommandBufferAndAcquireFence(gpucommandbuffer);
    }

    pub inline fn cancelGPUCommandBuffer(gpucommandbuffer: *GPUCommandBuffer) bool {
        return c.SDL_CancelGPUCommandBuffer(gpucommandbuffer);
    }
};

pub const GPURenderPass = opaque {
    pub inline fn bindGPUGraphicsPipeline(gpurenderpass: *GPURenderPass, graphics_pipeline: ?*GPUGraphicsPipeline) void {
        return c.SDL_BindGPUGraphicsPipeline(gpurenderpass, graphics_pipeline);
    }

    pub inline fn setGPUViewport(gpurenderpass: *GPURenderPass, viewport: *const GPUViewport) void {
        return c.SDL_SetGPUViewport(gpurenderpass, @ptrCast(viewport));
    }

    pub inline fn setGPUScissor(gpurenderpass: *GPURenderPass, scissor: *const Rect) void {
        return c.SDL_SetGPUScissor(gpurenderpass, @ptrCast(scissor));
    }

    pub inline fn setGPUBlendConstants(gpurenderpass: *GPURenderPass, blend_constants: FColor) void {
        return c.SDL_SetGPUBlendConstants(gpurenderpass, blend_constants);
    }

    pub inline fn setGPUStencilReference(gpurenderpass: *GPURenderPass, reference: u8) void {
        return c.SDL_SetGPUStencilReference(gpurenderpass, reference);
    }

    pub inline fn bindGPUVertexBuffers(gpurenderpass: *GPURenderPass, first_slot: u32, bindings: *const GPUBufferBinding, num_bindings: u32) void {
        return c.SDL_BindGPUVertexBuffers(gpurenderpass, first_slot, @ptrCast(bindings), num_bindings);
    }

    pub inline fn bindGPUIndexBuffer(gpurenderpass: *GPURenderPass, binding: *const GPUBufferBinding, index_element_size: GPUIndexElementSize) void {
        return c.SDL_BindGPUIndexBuffer(gpurenderpass, @ptrCast(binding), index_element_size);
    }

    pub inline fn bindGPUVertexSamplers(gpurenderpass: *GPURenderPass, first_slot: u32, texture_sampler_bindings: *const GPUTextureSamplerBinding, num_bindings: u32) void {
        return c.SDL_BindGPUVertexSamplers(gpurenderpass, first_slot, @ptrCast(texture_sampler_bindings), num_bindings);
    }

    pub inline fn bindGPUVertexStorageTextures(gpurenderpass: *GPURenderPass, first_slot: u32, storage_textures: [*c]*const GPUTexture, num_bindings: u32) void {
        return c.SDL_BindGPUVertexStorageTextures(gpurenderpass, first_slot, storage_textures, num_bindings);
    }

    pub inline fn bindGPUVertexStorageBuffers(gpurenderpass: *GPURenderPass, first_slot: u32, storage_buffers: [*c]*const GPUBuffer, num_bindings: u32) void {
        return c.SDL_BindGPUVertexStorageBuffers(gpurenderpass, first_slot, storage_buffers, num_bindings);
    }

    pub inline fn bindGPUFragmentSamplers(gpurenderpass: *GPURenderPass, first_slot: u32, texture_sampler_bindings: *const GPUTextureSamplerBinding, num_bindings: u32) void {
        return c.SDL_BindGPUFragmentSamplers(gpurenderpass, first_slot, @ptrCast(texture_sampler_bindings), num_bindings);
    }

    pub inline fn bindGPUFragmentStorageTextures(gpurenderpass: *GPURenderPass, first_slot: u32, storage_textures: [*c]*const GPUTexture, num_bindings: u32) void {
        return c.SDL_BindGPUFragmentStorageTextures(gpurenderpass, first_slot, storage_textures, num_bindings);
    }

    pub inline fn bindGPUFragmentStorageBuffers(gpurenderpass: *GPURenderPass, first_slot: u32, storage_buffers: [*c]*const GPUBuffer, num_bindings: u32) void {
        return c.SDL_BindGPUFragmentStorageBuffers(gpurenderpass, first_slot, storage_buffers, num_bindings);
    }

    pub inline fn drawGPUIndexedPrimitives(gpurenderpass: *GPURenderPass, num_indices: u32, num_instances: u32, first_index: u32, vertex_offset: i32, first_instance: u32) void {
        return c.SDL_DrawGPUIndexedPrimitives(gpurenderpass, num_indices, num_instances, first_index, vertex_offset, first_instance);
    }

    pub inline fn drawGPUPrimitives(gpurenderpass: *GPURenderPass, num_vertices: u32, num_instances: u32, first_vertex: u32, first_instance: u32) void {
        return c.SDL_DrawGPUPrimitives(gpurenderpass, num_vertices, num_instances, first_vertex, first_instance);
    }

    pub inline fn drawGPUPrimitivesIndirect(gpurenderpass: *GPURenderPass, buffer: ?*GPUBuffer, offset: u32, draw_count: u32) void {
        return c.SDL_DrawGPUPrimitivesIndirect(gpurenderpass, buffer, offset, draw_count);
    }

    pub inline fn drawGPUIndexedPrimitivesIndirect(gpurenderpass: *GPURenderPass, buffer: ?*GPUBuffer, offset: u32, draw_count: u32) void {
        return c.SDL_DrawGPUIndexedPrimitivesIndirect(gpurenderpass, buffer, offset, draw_count);
    }

    pub inline fn endGPURenderPass(gpurenderpass: *GPURenderPass) void {
        return c.SDL_EndGPURenderPass(gpurenderpass);
    }
};

pub const GPUComputePass = opaque {
    pub inline fn bindGPUComputePipeline(gpucomputepass: *GPUComputePass, compute_pipeline: ?*GPUComputePipeline) void {
        return c.SDL_BindGPUComputePipeline(gpucomputepass, compute_pipeline);
    }

    pub inline fn bindGPUComputeSamplers(gpucomputepass: *GPUComputePass, first_slot: u32, texture_sampler_bindings: *const GPUTextureSamplerBinding, num_bindings: u32) void {
        return c.SDL_BindGPUComputeSamplers(gpucomputepass, first_slot, @ptrCast(texture_sampler_bindings), num_bindings);
    }

    pub inline fn bindGPUComputeStorageTextures(gpucomputepass: *GPUComputePass, first_slot: u32, storage_textures: [*c]*const GPUTexture, num_bindings: u32) void {
        return c.SDL_BindGPUComputeStorageTextures(gpucomputepass, first_slot, storage_textures, num_bindings);
    }

    pub inline fn bindGPUComputeStorageBuffers(gpucomputepass: *GPUComputePass, first_slot: u32, storage_buffers: [*c]*const GPUBuffer, num_bindings: u32) void {
        return c.SDL_BindGPUComputeStorageBuffers(gpucomputepass, first_slot, storage_buffers, num_bindings);
    }

    pub inline fn dispatchGPUCompute(gpucomputepass: *GPUComputePass, groupcount_x: u32, groupcount_y: u32, groupcount_z: u32) void {
        return c.SDL_DispatchGPUCompute(gpucomputepass, groupcount_x, groupcount_y, groupcount_z);
    }

    pub inline fn dispatchGPUComputeIndirect(gpucomputepass: *GPUComputePass, buffer: ?*GPUBuffer, offset: u32) void {
        return c.SDL_DispatchGPUComputeIndirect(gpucomputepass, buffer, offset);
    }

    pub inline fn endGPUComputePass(gpucomputepass: *GPUComputePass) void {
        return c.SDL_EndGPUComputePass(gpucomputepass);
    }
};

pub const GPUCopyPass = opaque {
    pub inline fn uploadToGPUTexture(gpucopypass: *GPUCopyPass, source: *const GPUTextureTransferInfo, destination: *const GPUTextureRegion, cycle: bool) void {
        return c.SDL_UploadToGPUTexture(gpucopypass, @ptrCast(source), @ptrCast(destination), cycle);
    }

    pub inline fn uploadToGPUBuffer(gpucopypass: *GPUCopyPass, source: *const GPUTransferBufferLocation, destination: *const GPUBufferRegion, cycle: bool) void {
        return c.SDL_UploadToGPUBuffer(gpucopypass, @ptrCast(source), @ptrCast(destination), cycle);
    }

    pub inline fn copyGPUTextureToTexture(gpucopypass: *GPUCopyPass, source: *const GPUTextureLocation, destination: *const GPUTextureLocation, w: u32, h: u32, d: u32, cycle: bool) void {
        return c.SDL_CopyGPUTextureToTexture(gpucopypass, @ptrCast(source), @ptrCast(destination), w, h, d, cycle);
    }

    pub inline fn copyGPUBufferToBuffer(gpucopypass: *GPUCopyPass, source: *const GPUBufferLocation, destination: *const GPUBufferLocation, size: u32, cycle: bool) void {
        return c.SDL_CopyGPUBufferToBuffer(gpucopypass, @ptrCast(source), @ptrCast(destination), size, cycle);
    }

    pub inline fn downloadFromGPUTexture(gpucopypass: *GPUCopyPass, source: *const GPUTextureRegion, destination: *const GPUTextureTransferInfo) void {
        return c.SDL_DownloadFromGPUTexture(gpucopypass, @ptrCast(source), @ptrCast(destination));
    }

    pub inline fn downloadFromGPUBuffer(gpucopypass: *GPUCopyPass, source: *const GPUBufferRegion, destination: *const GPUTransferBufferLocation) void {
        return c.SDL_DownloadFromGPUBuffer(gpucopypass, @ptrCast(source), @ptrCast(destination));
    }

    pub inline fn endGPUCopyPass(gpucopypass: *GPUCopyPass) void {
        return c.SDL_EndGPUCopyPass(gpucopypass);
    }
};

pub const GPUFence = opaque {};

pub const GPUPrimitiveType = enum(c_int) {
    primitivetypeTrianglelist, //A series of separate triangles.
    primitivetypeTrianglestrip, //A series of connected triangles.
    primitivetypeLinelist, //A series of separate lines.
    primitivetypeLinestrip, //A series of connected lines.
    primitivetypePointlist, //A series of separate points.
};

pub const GPULoadOp = enum(c_int) {
    loadopLoad, //The previous contents of the texture will be preserved.
    loadopClear, //The contents of the texture will be cleared to a color.
    loadopDontCare, //The previous contents of the texture need not be preserved. The contents will be undefined.
};

pub const GPUStoreOp = enum(c_int) {
    storeopStore, //The contents generated during the render pass will be written to memory.
    storeopDontCare, //The contents generated during the render pass are not needed and may be discarded. The contents will be undefined.
    storeopResolve, //The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture may then be discarded and will be undefined.
    storeopResolveAndStore, //The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture will be written to memory.
};

pub const GPUIndexElementSize = enum(c_int) {
    indexelementsize16bit, //The index elements are 16-bit.
    indexelementsize32bit, //The index elements are 32-bit.
};

pub const GPUTextureFormat = enum(c_int) {
    textureformatInvalid,
    textureformatA8Unorm,
    textureformatR8Unorm,
    textureformatR8g8Unorm,
    textureformatR8g8b8a8Unorm,
    textureformatR16Unorm,
    textureformatR16g16Unorm,
    textureformatR16g16b16a16Unorm,
    textureformatR10g10b10a2Unorm,
    textureformatB5g6r5Unorm,
    textureformatB5g5r5a1Unorm,
    textureformatB4g4r4a4Unorm,
    textureformatB8g8r8a8Unorm,
    textureformatBc1RgbaUnorm,
    textureformatBc2RgbaUnorm,
    textureformatBc3RgbaUnorm,
    textureformatBc4RUnorm,
    textureformatBc5RgUnorm,
    textureformatBc7RgbaUnorm,
    textureformatBc6hRgbFloat,
    textureformatBc6hRgbUfloat,
    textureformatR8Snorm,
    textureformatR8g8Snorm,
    textureformatR8g8b8a8Snorm,
    textureformatR16Snorm,
    textureformatR16g16Snorm,
    textureformatR16g16b16a16Snorm,
    textureformatR16Float,
    textureformatR16g16Float,
    textureformatR16g16b16a16Float,
    textureformatR32Float,
    textureformatR32g32Float,
    textureformatR32g32b32a32Float,
    textureformatR11g11b10Ufloat,
    textureformatR8Uint,
    textureformatR8g8Uint,
    textureformatR8g8b8a8Uint,
    textureformatR16Uint,
    textureformatR16g16Uint,
    textureformatR16g16b16a16Uint,
    textureformatR32Uint,
    textureformatR32g32Uint,
    textureformatR32g32b32a32Uint,
    textureformatR8Int,
    textureformatR8g8Int,
    textureformatR8g8b8a8Int,
    textureformatR16Int,
    textureformatR16g16Int,
    textureformatR16g16b16a16Int,
    textureformatR32Int,
    textureformatR32g32Int,
    textureformatR32g32b32a32Int,
    textureformatR8g8b8a8UnormSrgb,
    textureformatB8g8r8a8UnormSrgb,
    textureformatBc1RgbaUnormSrgb,
    textureformatBc2RgbaUnormSrgb,
    textureformatBc3RgbaUnormSrgb,
    textureformatBc7RgbaUnormSrgb,
    textureformatD16Unorm,
    textureformatD24Unorm,
    textureformatD32Float,
    textureformatD24UnormS8Uint,
    textureformatD32FloatS8Uint,
    textureformatAstc4x4Unorm,
    textureformatAstc5x4Unorm,
    textureformatAstc5x5Unorm,
    textureformatAstc6x5Unorm,
    textureformatAstc6x6Unorm,
    textureformatAstc8x5Unorm,
    textureformatAstc8x6Unorm,
    textureformatAstc8x8Unorm,
    textureformatAstc10x5Unorm,
    textureformatAstc10x6Unorm,
    textureformatAstc10x8Unorm,
    textureformatAstc10x10Unorm,
    textureformatAstc12x10Unorm,
    textureformatAstc12x12Unorm,
    textureformatAstc4x4UnormSrgb,
    textureformatAstc5x4UnormSrgb,
    textureformatAstc5x5UnormSrgb,
    textureformatAstc6x5UnormSrgb,
    textureformatAstc6x6UnormSrgb,
    textureformatAstc8x5UnormSrgb,
    textureformatAstc8x6UnormSrgb,
    textureformatAstc8x8UnormSrgb,
    textureformatAstc10x5UnormSrgb,
    textureformatAstc10x6UnormSrgb,
    textureformatAstc10x8UnormSrgb,
    textureformatAstc10x10UnormSrgb,
    textureformatAstc12x10UnormSrgb,
    textureformatAstc12x12UnormSrgb,
    textureformatAstc4x4Float,
    textureformatAstc5x4Float,
    textureformatAstc5x5Float,
    textureformatAstc6x5Float,
    textureformatAstc6x6Float,
    textureformatAstc8x5Float,
    textureformatAstc8x6Float,
    textureformatAstc8x8Float,
    textureformatAstc10x5Float,
    textureformatAstc10x6Float,
    textureformatAstc10x8Float,
    textureformatAstc10x10Float,
    textureformatAstc12x10Float,
    textureformatAstc12x12Float,
};

pub const GPUTextureUsageFlags = packed struct(u32) {
    textureusageSampler: bool = false, // Texture supports sampling.
    textureusageColorTarget: bool = false, // Texture is a color render target.
    textureusageDepthStencilTarget: bool = false, // Texture is a depth stencil target.
    textureusageGraphicsStorageRead: bool = false, // Texture supports storage reads in graphics stages.
    textureusageComputeStorageRead: bool = false, // Texture supports storage reads in the compute stage.
    textureusageComputeStorageWrite: bool = false, // Texture supports storage writes in the compute stage.
    textureusageComputeStorageSimultaneousReadWrite: bool = false, // Texture supports reads and writes in the same compute shader. This is NOT equivalent to READ | WRITE.
    pad0: u24 = 0,
    rsvd: bool = false,
};

pub const GPUTextureType = enum(c_int) {
    texturetype2d, //The texture is a 2-dimensional image.
    texturetype2dArray, //The texture is a 2-dimensional array image.
    texturetype3d, //The texture is a 3-dimensional image.
    texturetypeCube, //The texture is a cube image.
    texturetypeCubeArray, //The texture is a cube array image.
};

pub const GPUSampleCount = enum(c_int) {
    samplecount1, //No multisampling.
    samplecount2, //MSAA 2x
    samplecount4, //MSAA 4x
    samplecount8, //MSAA 8x
};

pub const GPUCubeMapFace = enum(c_int) {
    cubemapfacePositivex,
    cubemapfaceNegativex,
    cubemapfacePositivey,
    cubemapfaceNegativey,
    cubemapfacePositivez,
    cubemapfaceNegativez,
};

pub const GPUBufferUsageFlags = packed struct(u32) {
    bufferusageVertex: bool = false, // Buffer is a vertex buffer.
    bufferusageIndex: bool = false, // Buffer is an index buffer.
    bufferusageIndirect: bool = false, // Buffer is an indirect buffer.
    bufferusageGraphicsStorageRead: bool = false, // Buffer supports storage reads in graphics stages.
    bufferusageComputeStorageRead: bool = false, // Buffer supports storage reads in the compute stage.
    bufferusageComputeStorageWrite: bool = false, // Buffer supports storage writes in the compute stage.
    pad0: u25 = 0,
    rsvd: bool = false,
};

pub const GPUTransferBufferUsage = enum(c_int) {
    transferbufferusageUpload,
    transferbufferusageDownload,
};

pub const GPUShaderStage = enum(c_int) {
    shaderstageVertex,
    shaderstageFragment,
};

pub const GPUShaderFormat = u32;

pub const GPUVertexElementFormat = enum(c_int) {
    vertexelementformatInvalid,
    vertexelementformatInt,
    vertexelementformatInt2,
    vertexelementformatInt3,
    vertexelementformatInt4,
    vertexelementformatUint,
    vertexelementformatUint2,
    vertexelementformatUint3,
    vertexelementformatUint4,
    vertexelementformatFloat,
    vertexelementformatFloat2,
    vertexelementformatFloat3,
    vertexelementformatFloat4,
    vertexelementformatByte2,
    vertexelementformatByte4,
    vertexelementformatUbyte2,
    vertexelementformatUbyte4,
    vertexelementformatByte2Norm,
    vertexelementformatByte4Norm,
    vertexelementformatUbyte2Norm,
    vertexelementformatUbyte4Norm,
    vertexelementformatShort2,
    vertexelementformatShort4,
    vertexelementformatUshort2,
    vertexelementformatUshort4,
    vertexelementformatShort2Norm,
    vertexelementformatShort4Norm,
    vertexelementformatUshort2Norm,
    vertexelementformatUshort4Norm,
    vertexelementformatHalf2,
    vertexelementformatHalf4,
};

pub const GPUVertexInputRate = enum(c_int) {
    vertexinputrateVertex, //Attribute addressing is a function of the vertex index.
    vertexinputrateInstance, //Attribute addressing is a function of the instance index.
};

pub const GPUFillMode = enum(c_int) {
    fillmodeFill, //Polygons will be rendered via rasterization.
    fillmodeLine, //Polygon edges will be drawn as line segments.
};

pub const GPUCullMode = enum(c_int) {
    cullmodeNone, //No triangles are culled.
    cullmodeFront, //Front-facing triangles are culled.
    cullmodeBack, //Back-facing triangles are culled.
};

pub const GPUFrontFace = enum(c_int) {
    frontfaceCounterClockwise, //A triangle with counter-clockwise vertex winding will be considered front-facing.
    frontfaceClockwise, //A triangle with clockwise vertex winding will be considered front-facing.
};

pub const GPUCompareOp = enum(c_int) {
    compareopInvalid,
    compareopNever, //The comparison always evaluates false.
    compareopLess, //The comparison evaluates reference < test.
    compareopEqual, //The comparison evaluates reference == test.
    compareopLessOrEqual, //The comparison evaluates reference <= test.
    compareopGreater, //The comparison evaluates reference > test.
    compareopNotEqual, //The comparison evaluates reference != test.
    compareopGreaterOrEqual, //The comparison evaluates reference >= test.
    compareopAlways, //The comparison always evaluates true.
};

pub const GPUStencilOp = enum(c_int) {
    stencilopInvalid,
    stencilopKeep, //Keeps the current value.
    stencilopZero, //Sets the value to 0.
    stencilopReplace, //Sets the value to reference.
    stencilopIncrementAndClamp, //Increments the current value and clamps to the maximum value.
    stencilopDecrementAndClamp, //Decrements the current value and clamps to 0.
    stencilopInvert, //Bitwise-inverts the current value.
    stencilopIncrementAndWrap, //Increments the current value and wraps back to 0.
    stencilopDecrementAndWrap, //Decrements the current value and wraps to the maximum value.
};

pub const GPUBlendOp = enum(c_int) {
    blendopInvalid,
    blendopAdd, //(source * source_factor) + (destination * destination_factor)
    blendopSubtract, //(source * source_factor) - (destination * destination_factor)
    blendopReverseSubtract, //(destination * destination_factor) - (source * source_factor)
    blendopMin, //min(source, destination)
    blendopMax,
};

pub const GPUBlendFactor = enum(c_int) {
    blendfactorInvalid,
    blendfactorZero, //0
    blendfactorOne, //1
    blendfactorSrcColor, //source color
    blendfactorOneMinusSrcColor, //1 - source color
    blendfactorDstColor, //destination color
    blendfactorOneMinusDstColor, //1 - destination color
    blendfactorSrcAlpha, //source alpha
    blendfactorOneMinusSrcAlpha, //1 - source alpha
    blendfactorDstAlpha, //destination alpha
    blendfactorOneMinusDstAlpha, //1 - destination alpha
    blendfactorConstantColor, //blend constant
    blendfactorOneMinusConstantColor, //1 - blend constant
    blendfactorSrcAlphaSaturate,
};

pub const GPUColorComponentFlags = packed struct(u8) {
    colorcomponentR: bool = false, // the red component
    colorcomponentG: bool = false, // the green component
    colorcomponentB: bool = false, // the blue component
    colorcomponentA: bool = false, // the alpha component
    pad0: u3 = 0,
    rsvd: bool = false,
};

pub const GPUFilter = enum(c_int) {
    filterNearest, //Point filtering.
    filterLinear, //Linear filtering.
};

pub const GPUSamplerMipmapMode = enum(c_int) {
    samplermipmapmodeNearest, //Point filtering.
    samplermipmapmodeLinear, //Linear filtering.
};

pub const GPUSamplerAddressMode = enum(c_int) {
    sampleraddressmodeRepeat, //Specifies that the coordinates will wrap around.
    sampleraddressmodeMirroredRepeat, //Specifies that the coordinates will wrap around mirrored.
    sampleraddressmodeClampToEdge, //Specifies that the coordinates will clamp to the 0-1 range.
};

pub const GPUPresentMode = enum(c_int) {
    presentmodeVsync,
    presentmodeImmediate,
    presentmodeMailbox,
};

pub const GPUSwapchainComposition = enum(c_int) {
    swapchaincompositionSdr,
    swapchaincompositionSdrLinear,
    swapchaincompositionHdrExtendedLinear,
    swapchaincompositionHdr10St2084,
};

pub const GPUViewport = extern struct {
    x: f32, // The left offset of the viewport.
    y: f32, // The top offset of the viewport.
    w: f32, // The width of the viewport.
    h: f32, // The height of the viewport.
    min_depth: f32, // The minimum depth of the viewport.
    max_depth: f32, // The maximum depth of the viewport.
};

pub const GPUTextureTransferInfo = extern struct {
    transfer_buffer: ?*GPUTransferBuffer, // The transfer buffer used in the transfer operation.
    offset: u32, // The starting byte of the image data in the transfer buffer.
    pixels_per_row: u32, // The number of pixels from one row to the next.
    rows_per_layer: u32, // The number of rows from one layer/depth-slice to the next.
};

pub const GPUTransferBufferLocation = extern struct {
    transfer_buffer: ?*GPUTransferBuffer, // The transfer buffer used in the transfer operation.
    offset: u32, // The starting byte of the buffer data in the transfer buffer.
};

pub const GPUTextureLocation = extern struct {
    texture: ?*GPUTexture, // The texture used in the copy operation.
    mip_level: u32, // The mip level index of the location.
    layer: u32, // The layer index of the location.
    x: u32, // The left offset of the location.
    y: u32, // The top offset of the location.
    z: u32, // The front offset of the location.
};

pub const GPUTextureRegion = extern struct {
    texture: ?*GPUTexture, // The texture used in the copy operation.
    mip_level: u32, // The mip level index to transfer.
    layer: u32, // The layer index to transfer.
    x: u32, // The left offset of the region.
    y: u32, // The top offset of the region.
    z: u32, // The front offset of the region.
    w: u32, // The width of the region.
    h: u32, // The height of the region.
    d: u32, // The depth of the region.
};

pub const GPUBlitRegion = extern struct {
    texture: ?*GPUTexture, // The texture.
    mip_level: u32, // The mip level index of the region.
    layer_or_depth_plane: u32, // The layer index or depth plane of the region. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures.
    x: u32, // The left offset of the region.
    y: u32, // The top offset of the region.
    w: u32, // The width of the region.
    h: u32, // The height of the region.
};

pub const GPUBufferLocation = extern struct {
    buffer: ?*GPUBuffer, // The buffer.
    offset: u32, // The starting byte within the buffer.
};

pub const GPUBufferRegion = extern struct {
    buffer: ?*GPUBuffer, // The buffer.
    offset: u32, // The starting byte within the buffer.
    size: u32, // The size in bytes of the region.
};

pub const GPUIndirectDrawCommand = extern struct {
    num_vertices: u32, // The number of vertices to draw.
    num_instances: u32, // The number of instances to draw.
    first_vertex: u32, // The index of the first vertex to draw.
    first_instance: u32, // The ID of the first instance to draw.
};

pub const GPUIndexedIndirectDrawCommand = extern struct {
    num_indices: u32, // The number of indices to draw per instance.
    num_instances: u32, // The number of instances to draw.
    first_index: u32, // The base index within the index buffer.
    vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
    first_instance: u32, // The ID of the first instance to draw.
};

pub const GPUIndirectDispatchCommand = extern struct {
    groupcount_x: u32, // The number of local workgroups to dispatch in the X dimension.
    groupcount_y: u32, // The number of local workgroups to dispatch in the Y dimension.
    groupcount_z: u32, // The number of local workgroups to dispatch in the Z dimension.
};

pub const GPUSamplerCreateInfo = extern struct {
    min_filter: GPUFilter, // The minification filter to apply to lookups.
    mag_filter: GPUFilter, // The magnification filter to apply to lookups.
    mipmap_mode: GPUSamplerMipmapMode, // The mipmap filter to apply to lookups.
    address_mode_u: GPUSamplerAddressMode, // The addressing mode for U coordinates outside [0, 1).
    address_mode_v: GPUSamplerAddressMode, // The addressing mode for V coordinates outside [0, 1).
    address_mode_w: GPUSamplerAddressMode, // The addressing mode for W coordinates outside [0, 1).
    mip_lod_bias: f32, // The bias to be added to mipmap LOD calculation.
    max_anisotropy: f32, // The anisotropy value clamp used by the sampler. If enable_anisotropy is false, this is ignored.
    compare_op: GPUCompareOp, // The comparison operator to apply to fetched data before filtering.
    min_lod: f32, // Clamps the minimum of the computed LOD value.
    max_lod: f32, // Clamps the maximum of the computed LOD value.
    enable_anisotropy: bool, // true to enable anisotropic filtering.
    enable_compare: bool, // true to enable comparison against a reference value during lookups.
    padding1: u8,
    padding2: u8,
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUVertexBufferDescription = extern struct {
    slot: u32, // The binding slot of the vertex buffer.
    pitch: u32, // The size of a single element + the offset between elements.
    input_rate: GPUVertexInputRate, // Whether attribute addressing is a function of the vertex index or instance index.
    instance_step_rate: u32, // Reserved for future use. Must be set to 0.
};

pub const GPUVertexAttribute = extern struct {
    location: u32, // The shader input location index.
    buffer_slot: u32, // The binding slot of the associated vertex buffer.
    format: GPUVertexElementFormat, // The size and type of the attribute data.
    offset: u32, // The byte offset of this attribute relative to the start of the vertex element.
};

pub const GPUVertexInputState = extern struct {
    vertex_buffer_descriptions: *const GPUVertexBufferDescription, // A pointer to an array of vertex buffer descriptions.
    num_vertex_buffers: u32, // The number of vertex buffer descriptions in the above array.
    vertex_attributes: *const GPUVertexAttribute, // A pointer to an array of vertex attribute descriptions.
    num_vertex_attributes: u32, // The number of vertex attribute descriptions in the above array.
};

pub const GPUStencilOpState = extern struct {
    fail_op: GPUStencilOp, // The action performed on samples that fail the stencil test.
    pass_op: GPUStencilOp, // The action performed on samples that pass the depth and stencil tests.
    depth_fail_op: GPUStencilOp, // The action performed on samples that pass the stencil test and fail the depth test.
    compare_op: GPUCompareOp, // The comparison operator used in the stencil test.
};

pub const GPUColorTargetBlendState = extern struct {
    src_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the source RGB value.
    dst_color_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination RGB value.
    color_blend_op: GPUBlendOp, // The blend operation for the RGB components.
    src_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the source alpha.
    dst_alpha_blendfactor: GPUBlendFactor, // The value to be multiplied by the destination alpha.
    alpha_blend_op: GPUBlendOp, // The blend operation for the alpha component.
    color_write_mask: GPUColorComponentFlags, // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false.
    enable_blend: bool, // Whether blending is enabled for the color target.
    enable_color_write_mask: bool, // Whether the color write mask is enabled.
    padding1: u8,
    padding2: u8,
};

pub const GPUShaderCreateInfo = extern struct {
    code_size: usize, // The size in bytes of the code pointed to.
    code: [*c]const u8, // A pointer to shader code.
    entrypoint: [*c]const u8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader.
    format: GPUShaderFormat, // The format of the shader code.
    stage: GPUShaderStage, // The stage the shader program corresponds to.
    num_samplers: u32, // The number of samplers defined in the shader.
    num_storage_textures: u32, // The number of storage textures defined in the shader.
    num_storage_buffers: u32, // The number of storage buffers defined in the shader.
    num_uniform_buffers: u32, // The number of uniform buffers defined in the shader.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUTextureCreateInfo = extern struct {
    _type: GPUTextureType, // The base dimensionality of the texture.
    format: GPUTextureFormat, // The pixel format of the texture.
    usage: GPUTextureUsageFlags, // How the texture is intended to be used by the client.
    width: u32, // The width of the texture.
    height: u32, // The height of the texture.
    layer_count_or_depth: u32, // The layer count or depth of the texture. This value is treated as a layer count on 2D array textures, and as a depth value on 3D textures.
    num_levels: u32, // The number of mip levels in the texture.
    sample_count: GPUSampleCount, // The number of samples per texel. Only applies if the texture is used as a render target.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUBufferCreateInfo = extern struct {
    usage: GPUBufferUsageFlags, // How the buffer is intended to be used by the client.
    size: u32, // The size in bytes of the buffer.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUTransferBufferCreateInfo = extern struct {
    usage: GPUTransferBufferUsage, // How the transfer buffer is intended to be used by the client.
    size: u32, // The size in bytes of the transfer buffer.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPURasterizerState = extern struct {
    fill_mode: GPUFillMode, // Whether polygons will be filled in or drawn as lines.
    cull_mode: GPUCullMode, // The facing direction in which triangles will be culled.
    front_face: GPUFrontFace, // The vertex winding that will cause a triangle to be determined as front-facing.
    depth_bias_constant_factor: f32, // A scalar factor controlling the depth value added to each fragment.
    depth_bias_clamp: f32, // The maximum depth bias of a fragment.
    depth_bias_slope_factor: f32, // A scalar factor applied to a fragment's slope in depth calculations.
    enable_depth_bias: bool, // true to bias fragment depth values.
    enable_depth_clip: bool, // true to enable depth clip, false to enable depth clamp.
    padding1: u8,
    padding2: u8,
};

pub const GPUMultisampleState = extern struct {
    sample_count: GPUSampleCount, // The number of samples to be used in rasterization.
    sample_mask: u32, // Reserved for future use. Must be set to 0.
    enable_mask: bool, // Reserved for future use. Must be set to false.
    enable_alpha_to_coverage: bool, // true enables the alpha-to-coverage feature.
    padding2: u8,
    padding3: u8,
};

pub const GPUDepthStencilState = extern struct {
    compare_op: GPUCompareOp, // The comparison operator used for depth testing.
    back_stencil_state: GPUStencilOpState, // The stencil op state for back-facing triangles.
    front_stencil_state: GPUStencilOpState, // The stencil op state for front-facing triangles.
    compare_mask: u8, // Selects the bits of the stencil values participating in the stencil test.
    write_mask: u8, // Selects the bits of the stencil values updated by the stencil test.
    enable_depth_test: bool, // true enables the depth test.
    enable_depth_write: bool, // true enables depth writes. Depth writes are always disabled when enable_depth_test is false.
    enable_stencil_test: bool, // true enables the stencil test.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const GPUColorTargetDescription = extern struct {
    format: GPUTextureFormat, // The pixel format of the texture to be used as a color target.
    blend_state: GPUColorTargetBlendState, // The blend state to be used for the color target.
};

pub const GPUGraphicsPipelineTargetInfo = extern struct {
    color_target_descriptions: *const GPUColorTargetDescription, // A pointer to an array of color target descriptions.
    num_color_targets: u32, // The number of color target descriptions in the above array.
    depth_stencil_format: GPUTextureFormat, // The pixel format of the depth-stencil target. Ignored if has_depth_stencil_target is false.
    has_depth_stencil_target: bool, // true specifies that the pipeline uses a depth-stencil target.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const GPUGraphicsPipelineCreateInfo = extern struct {
    vertex_shader: ?*GPUShader, // The vertex shader used by the graphics pipeline.
    fragment_shader: ?*GPUShader, // The fragment shader used by the graphics pipeline.
    vertex_input_state: GPUVertexInputState, // The vertex layout of the graphics pipeline.
    primitive_type: GPUPrimitiveType, // The primitive topology of the graphics pipeline.
    rasterizer_state: GPURasterizerState, // The rasterizer state of the graphics pipeline.
    multisample_state: GPUMultisampleState, // The multisample state of the graphics pipeline.
    depth_stencil_state: GPUDepthStencilState, // The depth-stencil state of the graphics pipeline.
    target_info: GPUGraphicsPipelineTargetInfo, // Formats and blend modes for the render targets of the graphics pipeline.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUComputePipelineCreateInfo = extern struct {
    code_size: usize, // The size in bytes of the compute shader code pointed to.
    code: [*c]const u8, // A pointer to compute shader code.
    entrypoint: [*c]const u8, // A pointer to a null-terminated UTF-8 string specifying the entry point function name for the shader.
    format: GPUShaderFormat, // The format of the compute shader code.
    num_samplers: u32, // The number of samplers defined in the shader.
    num_readonly_storage_textures: u32, // The number of readonly storage textures defined in the shader.
    num_readonly_storage_buffers: u32, // The number of readonly storage buffers defined in the shader.
    num_readwrite_storage_textures: u32, // The number of read-write storage textures defined in the shader.
    num_readwrite_storage_buffers: u32, // The number of read-write storage buffers defined in the shader.
    num_uniform_buffers: u32, // The number of uniform buffers defined in the shader.
    threadcount_x: u32, // The number of threads in the X dimension. This should match the value in the shader.
    threadcount_y: u32, // The number of threads in the Y dimension. This should match the value in the shader.
    threadcount_z: u32, // The number of threads in the Z dimension. This should match the value in the shader.
    props: PropertiesID, // A properties ID for extensions. Should be 0 if no extensions are needed.
};

pub const GPUColorTargetInfo = extern struct {
    texture: ?*GPUTexture, // The texture that will be used as a color target by a render pass.
    mip_level: u32, // The mip level to use as a color target.
    layer_or_depth_plane: u32, // The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures.
    clear_color: FColor, // The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used.
    load_op: GPULoadOp, // What is done with the contents of the color target at the beginning of the render pass.
    store_op: GPUStoreOp, // What is done with the results of the render pass.
    resolve_texture: ?*GPUTexture, // The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used.
    resolve_mip_level: u32, // The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used.
    resolve_layer: u32, // The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used.
    cycle: bool, // true cycles the texture if the texture is bound and load_op is not LOAD
    cycle_resolve_texture: bool, // true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used.
    padding1: u8,
    padding2: u8,
};

pub const GPUDepthStencilTargetInfo = extern struct {
    texture: ?*GPUTexture, // The texture that will be used as the depth stencil target by the render pass.
    clear_depth: f32, // The value to clear the depth component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used.
    load_op: GPULoadOp, // What is done with the depth contents at the beginning of the render pass.
    store_op: GPUStoreOp, // What is done with the depth results of the render pass.
    stencil_load_op: GPULoadOp, // What is done with the stencil contents at the beginning of the render pass.
    stencil_store_op: GPUStoreOp, // What is done with the stencil results of the render pass.
    cycle: bool, // true cycles the texture if the texture is bound and any load ops are not LOAD
    clear_stencil: u8, // The value to clear the stencil component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used.
    mip_level: u8, // The mip level to use as the depth stencil target.
    layer: u8, // The layer index to use as the depth stencil target.
};

pub const GPUBlitInfo = extern struct {
    source: GPUBlitRegion, // The source region for the blit.
    destination: GPUBlitRegion, // The destination region for the blit.
    load_op: GPULoadOp, // What is done with the contents of the destination before the blit.
    clear_color: FColor, // The color to clear the destination region to before the blit. Ignored if load_op is not SDL_GPU_LOADOP_CLEAR.
    flip_mode: FlipMode, // The flip mode for the source region.
    filter: GPUFilter, // The filter mode used when blitting.
    cycle: bool, // true cycles the destination texture if it is already bound.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const GPUBufferBinding = extern struct {
    buffer: ?*GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_VERTEX for SDL_BindGPUVertexBuffers, or SDL_GPU_BUFFERUSAGE_INDEX for SDL_BindGPUIndexBuffer.
    offset: u32, // The starting byte of the data to bind in the buffer.
};

pub const GPUTextureSamplerBinding = extern struct {
    texture: ?*GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER.
    sampler: ?*GPUSampler, // The sampler to bind.
};

pub const GPUStorageBufferReadWriteBinding = extern struct {
    buffer: ?*GPUBuffer, // The buffer to bind. Must have been created with SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE.
    cycle: bool, // true cycles the buffer if it is already bound.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub const GPUStorageTextureReadWriteBinding = extern struct {
    texture: ?*GPUTexture, // The texture to bind. Must have been created with SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE or SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE.
    mip_level: u32, // The mip level index to bind.
    layer: u32, // The layer index to bind.
    cycle: bool, // true cycles the texture if it is already bound.
    padding1: u8,
    padding2: u8,
    padding3: u8,
};

pub inline fn gpuSupportsShaderFormats(format_flags: GPUShaderFormat, name: [*c]const u8) bool {
    return c.SDL_GPUSupportsShaderFormats(@bitCast(format_flags), name);
}

pub inline fn gpuSupportsProperties(props: PropertiesID) bool {
    return c.SDL_GPUSupportsProperties(props);
}

pub inline fn createGPUDevice(format_flags: GPUShaderFormat, debug_mode: bool, name: [*c]const u8) ?*GPUDevice {
    return c.SDL_CreateGPUDevice(@bitCast(format_flags), debug_mode, name);
}

pub inline fn createGPUDeviceWithProperties(props: PropertiesID) ?*GPUDevice {
    return c.SDL_CreateGPUDeviceWithProperties(props);
}

pub const GPUVulkanOptions = extern struct {
    vulkan_api_version: u32, // The Vulkan API version to request for the instance. Use Vulkan's VK_MAKE_VERSION or VK_MAKE_API_VERSION.
    feature_list: ?*anyopaque, // Pointer to the first element of a chain of Vulkan feature structs. (Requires API version 1.1 or higher.)
    vulkan_10_physical_device_features: ?*anyopaque, // Pointer to a VkPhysicalDeviceFeatures struct to enable additional Vulkan 1.0 features.
    device_extension_count: u32, // Number of additional device extensions to require.
    device_extension_names: [*c][*c]const u8, // Pointer to a list of additional device extensions to require.
    instance_extension_count: u32, // Number of additional instance extensions to require.
    instance_extension_names: [*c][*c]const u8, // Pointer to a list of additional instance extensions to require.
};

pub inline fn getNumGPUDrivers() c_int {
    return c.SDL_GetNumGPUDrivers();
}

pub inline fn getGPUDriver(index: c_int) [*c]const u8 {
    return c.SDL_GetGPUDriver(index);
}

pub inline fn gpuTextureFormatTexelBlockSize(format: GPUTextureFormat) u32 {
    return c.SDL_GPUTextureFormatTexelBlockSize(@bitCast(format));
}

pub inline fn calculateGPUTextureFormatSize(format: GPUTextureFormat, width: u32, height: u32, depth_or_layer_count: u32) u32 {
    return c.SDL_CalculateGPUTextureFormatSize(@bitCast(format), width, height, depth_or_layer_count);
}

pub inline fn getPixelFormatFromGPUTextureFormat(format: GPUTextureFormat) PixelFormat {
    return @bitCast(c.SDL_GetPixelFormatFromGPUTextureFormat(@bitCast(format)));
}

pub inline fn getGPUTextureFormatFromPixelFormat(format: PixelFormat) GPUTextureFormat {
    return @bitCast(c.SDL_GetGPUTextureFormatFromPixelFormat(@bitCast(format)));
}
