Cleanup
This commit is contained in:
@@ -4,10 +4,6 @@ import "core:log"
|
||||
import "core:mem"
|
||||
import sdl "vendor:sdl3"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Texture types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Texture_Id :: distinct u32
|
||||
INVALID_TEXTURE :: Texture_Id(0) // Slot 0 is reserved/unused
|
||||
|
||||
@@ -61,10 +57,6 @@ Texture_Slot :: struct {
|
||||
// GLOB.pending_texture_releases : [dynamic]Texture_Id
|
||||
// GLOB.samplers : [SAMPLER_PRESET_COUNT]^sdl.GPUSampler
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Clay integration type
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Clay_Image_Data :: struct {
|
||||
texture_id: Texture_Id,
|
||||
fit: Fit_Mode,
|
||||
@@ -75,9 +67,9 @@ clay_image_data :: proc(id: Texture_Id, fit: Fit_Mode = .Stretch, tint: Color =
|
||||
return {texture_id = id, fit = fit, tint = tint}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registration
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// ----- Registration -------------
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Register a texture. Draw owns the GPU resource and releases it on unregister.
|
||||
// `data` is tightly-packed row-major bytes matching desc.format.
|
||||
@@ -236,130 +228,9 @@ update_texture_region :: proc(id: Texture_Id, region: Rectangle, data: []u8) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Accessors
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
texture_size :: proc(id: Texture_Id) -> [2]u32 {
|
||||
if id == INVALID_TEXTURE do return {0, 0}
|
||||
slot := &GLOB.texture_slots[u32(id)]
|
||||
return {slot.desc.width, slot.desc.height}
|
||||
}
|
||||
|
||||
texture_format :: proc(id: Texture_Id) -> sdl.GPUTextureFormat {
|
||||
if id == INVALID_TEXTURE do return .INVALID
|
||||
return GLOB.texture_slots[u32(id)].desc.format
|
||||
}
|
||||
|
||||
texture_kind :: proc(id: Texture_Id) -> Texture_Kind {
|
||||
if id == INVALID_TEXTURE do return .Static
|
||||
return GLOB.texture_slots[u32(id)].desc.kind
|
||||
}
|
||||
|
||||
// Internal: get the raw GPU texture pointer for binding during draw.
|
||||
@(private)
|
||||
texture_gpu_handle :: proc(id: Texture_Id) -> ^sdl.GPUTexture {
|
||||
if id == INVALID_TEXTURE do return nil
|
||||
idx := u32(id)
|
||||
if idx >= u32(len(GLOB.texture_slots)) do return nil
|
||||
return GLOB.texture_slots[idx].gpu_texture
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Deferred release (called from draw.end / clear_global)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@(private)
|
||||
process_pending_texture_releases :: proc() {
|
||||
device := GLOB.device
|
||||
for id in GLOB.pending_texture_releases {
|
||||
idx := u32(id)
|
||||
if idx >= u32(len(GLOB.texture_slots)) do continue
|
||||
slot := &GLOB.texture_slots[idx]
|
||||
if slot.gpu_texture != nil {
|
||||
sdl.ReleaseGPUTexture(device, slot.gpu_texture)
|
||||
slot.gpu_texture = nil
|
||||
}
|
||||
slot.generation += 1
|
||||
append(&GLOB.texture_free_list, idx)
|
||||
}
|
||||
clear(&GLOB.pending_texture_releases)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sampler pool
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@(private)
|
||||
get_sampler :: proc(preset: Sampler_Preset) -> ^sdl.GPUSampler {
|
||||
idx := int(preset)
|
||||
if GLOB.samplers[idx] != nil do return GLOB.samplers[idx]
|
||||
|
||||
// Lazily create
|
||||
min_filter, mag_filter: sdl.GPUFilter
|
||||
address_mode: sdl.GPUSamplerAddressMode
|
||||
|
||||
switch preset {
|
||||
case .Nearest_Clamp:
|
||||
min_filter = .NEAREST; mag_filter = .NEAREST; address_mode = .CLAMP_TO_EDGE
|
||||
case .Linear_Clamp:
|
||||
min_filter = .LINEAR; mag_filter = .LINEAR; address_mode = .CLAMP_TO_EDGE
|
||||
case .Nearest_Repeat:
|
||||
min_filter = .NEAREST; mag_filter = .NEAREST; address_mode = .REPEAT
|
||||
case .Linear_Repeat:
|
||||
min_filter = .LINEAR; mag_filter = .LINEAR; address_mode = .REPEAT
|
||||
}
|
||||
|
||||
sampler := sdl.CreateGPUSampler(
|
||||
GLOB.device,
|
||||
sdl.GPUSamplerCreateInfo {
|
||||
min_filter = min_filter,
|
||||
mag_filter = mag_filter,
|
||||
mipmap_mode = .LINEAR,
|
||||
address_mode_u = address_mode,
|
||||
address_mode_v = address_mode,
|
||||
address_mode_w = address_mode,
|
||||
},
|
||||
)
|
||||
if sampler == nil {
|
||||
log.errorf("Failed to create sampler preset %v: %s", preset, sdl.GetError())
|
||||
return GLOB.pipeline_2d_base.sampler // fallback to existing default sampler
|
||||
}
|
||||
|
||||
GLOB.samplers[idx] = sampler
|
||||
return sampler
|
||||
}
|
||||
|
||||
// Internal: destroy all sampler pool entries. Called from draw.destroy().
|
||||
@(private)
|
||||
destroy_sampler_pool :: proc() {
|
||||
device := GLOB.device
|
||||
for &s in GLOB.samplers {
|
||||
if s != nil {
|
||||
sdl.ReleaseGPUSampler(device, s)
|
||||
s = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal: destroy all registered textures. Called from draw.destroy().
|
||||
@(private)
|
||||
destroy_all_textures :: proc() {
|
||||
device := GLOB.device
|
||||
for &slot in GLOB.texture_slots {
|
||||
if slot.gpu_texture != nil {
|
||||
sdl.ReleaseGPUTexture(device, slot.gpu_texture)
|
||||
slot.gpu_texture = nil
|
||||
}
|
||||
}
|
||||
delete(GLOB.texture_slots)
|
||||
delete(GLOB.texture_free_list)
|
||||
delete(GLOB.pending_texture_releases)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Fit mode helper
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// ----- Helpers -------------
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Compute UV rect, recommended sampler, and inner rect for a given fit mode.
|
||||
// `rect` is the target drawing area; `texture_id` identifies the texture whose
|
||||
@@ -431,3 +302,113 @@ fit_params :: proc(
|
||||
|
||||
return {0, 0, 1, 1}, .Linear_Clamp, inner_rect
|
||||
}
|
||||
|
||||
texture_size :: proc(id: Texture_Id) -> [2]u32 {
|
||||
if id == INVALID_TEXTURE do return {0, 0}
|
||||
slot := &GLOB.texture_slots[u32(id)]
|
||||
return {slot.desc.width, slot.desc.height}
|
||||
}
|
||||
|
||||
texture_format :: proc(id: Texture_Id) -> sdl.GPUTextureFormat {
|
||||
if id == INVALID_TEXTURE do return .INVALID
|
||||
return GLOB.texture_slots[u32(id)].desc.format
|
||||
}
|
||||
|
||||
texture_kind :: proc(id: Texture_Id) -> Texture_Kind {
|
||||
if id == INVALID_TEXTURE do return .Static
|
||||
return GLOB.texture_slots[u32(id)].desc.kind
|
||||
}
|
||||
|
||||
// Internal: get the raw GPU texture pointer for binding during draw.
|
||||
@(private)
|
||||
texture_gpu_handle :: proc(id: Texture_Id) -> ^sdl.GPUTexture {
|
||||
if id == INVALID_TEXTURE do return nil
|
||||
idx := u32(id)
|
||||
if idx >= u32(len(GLOB.texture_slots)) do return nil
|
||||
return GLOB.texture_slots[idx].gpu_texture
|
||||
}
|
||||
|
||||
// Deferred release (called from draw.end / clear_global)
|
||||
@(private)
|
||||
process_pending_texture_releases :: proc() {
|
||||
device := GLOB.device
|
||||
for id in GLOB.pending_texture_releases {
|
||||
idx := u32(id)
|
||||
if idx >= u32(len(GLOB.texture_slots)) do continue
|
||||
slot := &GLOB.texture_slots[idx]
|
||||
if slot.gpu_texture != nil {
|
||||
sdl.ReleaseGPUTexture(device, slot.gpu_texture)
|
||||
slot.gpu_texture = nil
|
||||
}
|
||||
slot.generation += 1
|
||||
append(&GLOB.texture_free_list, idx)
|
||||
}
|
||||
clear(&GLOB.pending_texture_releases)
|
||||
}
|
||||
|
||||
@(private)
|
||||
get_sampler :: proc(preset: Sampler_Preset) -> ^sdl.GPUSampler {
|
||||
idx := int(preset)
|
||||
if GLOB.samplers[idx] != nil do return GLOB.samplers[idx]
|
||||
|
||||
// Lazily create
|
||||
min_filter, mag_filter: sdl.GPUFilter
|
||||
address_mode: sdl.GPUSamplerAddressMode
|
||||
|
||||
switch preset {
|
||||
case .Nearest_Clamp:
|
||||
min_filter = .NEAREST; mag_filter = .NEAREST; address_mode = .CLAMP_TO_EDGE
|
||||
case .Linear_Clamp:
|
||||
min_filter = .LINEAR; mag_filter = .LINEAR; address_mode = .CLAMP_TO_EDGE
|
||||
case .Nearest_Repeat:
|
||||
min_filter = .NEAREST; mag_filter = .NEAREST; address_mode = .REPEAT
|
||||
case .Linear_Repeat:
|
||||
min_filter = .LINEAR; mag_filter = .LINEAR; address_mode = .REPEAT
|
||||
}
|
||||
|
||||
sampler := sdl.CreateGPUSampler(
|
||||
GLOB.device,
|
||||
sdl.GPUSamplerCreateInfo {
|
||||
min_filter = min_filter,
|
||||
mag_filter = mag_filter,
|
||||
mipmap_mode = .LINEAR,
|
||||
address_mode_u = address_mode,
|
||||
address_mode_v = address_mode,
|
||||
address_mode_w = address_mode,
|
||||
},
|
||||
)
|
||||
if sampler == nil {
|
||||
log.errorf("Failed to create sampler preset %v: %s", preset, sdl.GetError())
|
||||
return GLOB.pipeline_2d_base.sampler // fallback to existing default sampler
|
||||
}
|
||||
|
||||
GLOB.samplers[idx] = sampler
|
||||
return sampler
|
||||
}
|
||||
|
||||
// Internal: destroy all sampler pool entries. Called from draw.destroy().
|
||||
@(private)
|
||||
destroy_sampler_pool :: proc() {
|
||||
device := GLOB.device
|
||||
for &s in GLOB.samplers {
|
||||
if s != nil {
|
||||
sdl.ReleaseGPUSampler(device, s)
|
||||
s = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal: destroy all registered textures. Called from draw.destroy().
|
||||
@(private)
|
||||
destroy_all_textures :: proc() {
|
||||
device := GLOB.device
|
||||
for &slot in GLOB.texture_slots {
|
||||
if slot.gpu_texture != nil {
|
||||
sdl.ReleaseGPUTexture(device, slot.gpu_texture)
|
||||
slot.gpu_texture = nil
|
||||
}
|
||||
}
|
||||
delete(GLOB.texture_slots)
|
||||
delete(GLOB.texture_free_list)
|
||||
delete(GLOB.pending_texture_releases)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user