base: bc7 support

This commit is contained in:
luboslenco
2026-04-04 13:07:01 +02:00
parent 088ba1c03b
commit 4e113a3305
14 changed files with 330 additions and 187 deletions
+9 -1
View File
@@ -141,7 +141,10 @@ async function init() {
throw new Error('WebGPU not supported');
}
let adapter = await navigator.gpu.requestAdapter();
let device = await adapter.requestDevice();
let bc7_supported = adapter.features.has('texture-compression-bc');
let device = await adapter.requestDevice({
requiredFeatures: bc7_supported ? ['texture-compression-bc'] : [],
});
let canvas = document.getElementById('iron');
canvas.width = window.innerWidth;
@@ -182,6 +185,11 @@ async function init() {
wgpuAdapterRequestDeviceSync : function() {
return ptr_to_id(device);
},
wgpuDeviceHasFeature : function(pdevice, feature) {
// WGPUFeatureName_TextureCompressionBC = 4
if (feature === 4) { return bc7_supported ? 1 : 0; }
return 0;
},
wgpuDeviceCreateTexture : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUTextureDescriptor
+80 -41
View File
@@ -265,8 +265,7 @@ void gpu_render_target_init2(gpu_texture_t *render_target, int width, int height
.Texture2D.PlaneSlice = 0,
};
D3D12_CPU_DESCRIPTOR_HANDLE handle =
render_target->impl.is_dsv ? dsv_handle(render_target->impl.rtv_index) : rtv_handle(render_target->impl.rtv_index);
D3D12_CPU_DESCRIPTOR_HANDLE handle = render_target->impl.is_dsv ? dsv_handle(render_target->impl.rtv_index) : rtv_handle(render_target->impl.rtv_index);
if (format == GPU_TEXTURE_FORMAT_D32) {
device->lpVtbl->CreateDepthStencilView(device, render_target->impl.image, NULL, handle);
@@ -295,12 +294,12 @@ void create_root_signature(bool linear_sampling) {
ID3DBlob *error_blob;
D3D12_ROOT_PARAMETER parameters[3] = {0};
D3D12_DESCRIPTOR_RANGE range = {
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
.NumDescriptors = (UINT)GPU_MAX_TEXTURES,
.BaseShaderRegister = 0,
.RegisterSpace = 0,
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
};
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
.NumDescriptors = (UINT)GPU_MAX_TEXTURES,
.BaseShaderRegister = 0,
.RegisterSpace = 0,
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
};
parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
parameters[0].DescriptorTable.NumDescriptorRanges = 1;
@@ -310,12 +309,12 @@ void create_root_signature(bool linear_sampling) {
parameters[1].Descriptor.ShaderRegister = 0;
parameters[1].Descriptor.RegisterSpace = 0;
D3D12_DESCRIPTOR_RANGE sampler_range = {
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
.NumDescriptors = 1,
.BaseShaderRegister = 0,
.RegisterSpace = 0,
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
};
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
.NumDescriptors = 1,
.BaseShaderRegister = 0,
.RegisterSpace = 0,
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
};
parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
parameters[2].DescriptorTable.NumDescriptorRanges = 1;
@@ -444,8 +443,7 @@ void gpu_begin_internal(gpu_clear_t flags, unsigned color, float depth) {
command_list->lpVtbl->ClearRenderTargetView(command_list, rtv_handle(target->impl.rtv_index), clear_color, 0, NULL);
}
if (flags & GPU_CLEAR_DEPTH && current_depth_buffer != NULL) {
command_list->lpVtbl->ClearDepthStencilView(command_list, dsv_handle(current_depth_buffer->impl.rtv_index), D3D12_CLEAR_FLAG_DEPTH, depth, 0, 0,
NULL);
command_list->lpVtbl->ClearDepthStencilView(command_list, dsv_handle(current_depth_buffer->impl.rtv_index), D3D12_CLEAR_FLAG_DEPTH, depth, 0, 0, NULL);
}
}
@@ -550,8 +548,7 @@ void gpu_internal_set_textures() {
for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
if (current_textures[i] != NULL) {
device->lpVtbl->CopyDescriptorsSimple(device, 1, cpu_base, srv_handle(current_textures[i]->impl.srv_index),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
device->lpVtbl->CopyDescriptorsSimple(device, 1, cpu_base, srv_handle(current_textures[i]->impl.srv_index), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
cpu_base.ptr += srv_step;
gpu_srv_heap_index++;
}
@@ -833,8 +830,8 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipe) {
psoDesc.BlendState.IndependentBlendEnable = true;
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
psoDesc.BlendState.RenderTarget[i].BlendEnable = pipe->blend_source != GPU_BLEND_ONE || pipe->blend_destination != GPU_BLEND_ZERO ||
pipe->alpha_blend_source != GPU_BLEND_ONE || pipe->alpha_blend_destination != GPU_BLEND_ZERO;
psoDesc.BlendState.RenderTarget[i].BlendEnable = pipe->blend_source != GPU_BLEND_ONE || pipe->blend_destination != GPU_BLEND_ZERO ||
pipe->alpha_blend_source != GPU_BLEND_ONE || pipe->alpha_blend_destination != GPU_BLEND_ZERO;
psoDesc.BlendState.RenderTarget[i].SrcBlend = convert_blend_factor(pipe->blend_source);
psoDesc.BlendState.RenderTarget[i].DestBlend = convert_blend_factor(pipe->blend_destination);
psoDesc.BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
@@ -862,14 +859,23 @@ void gpu_shader_destroy(gpu_shader_t *shader) {
}
void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) {
texture->width = width;
texture->height = height;
texture->format = format;
texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE;
texture->buffer = NULL;
texture->impl.rtv_index = -1;
DXGI_FORMAT dxgi_format = convert_format(format);
int format_size = gpu_texture_format_size(format);
texture->width = width;
texture->height = height;
texture->format = format;
texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE;
texture->buffer = NULL;
texture->impl.rtv_index = -1;
DXGI_FORMAT dxgi_format = convert_format(format);
int format_size = gpu_texture_format_size(format);
void *original_data = data;
#ifdef WITH_BC7
if (gpu_bc7_supported(width, height, format)) {
texture->format = GPU_TEXTURE_FORMAT_RGBA32_BC7;
dxgi_format = DXGI_FORMAT_BC7_UNORM;
data = gpu_bc7_compress(data, width, height);
}
#endif
D3D12_HEAP_PROPERTIES heap_properties = {
.Type = D3D12_HEAP_TYPE_DEFAULT,
@@ -899,8 +905,13 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
if (result != S_OK && gpu_cleanup_pending()) {
gpu_execute_and_wait();
gpu_cleanup();
device->lpVtbl->CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
NULL, &IID_ID3D12Resource, &texture->impl.image);
#ifdef WITH_BC7
if (data != original_data) {
free(data);
}
#endif
gpu_texture_init_from_bytes(texture, original_data, width, height, format);
return;
}
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
@@ -946,8 +957,16 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
BYTE *pixel;
upload_buffer->lpVtbl->Map(upload_buffer, 0, NULL, (void **)&pixel);
UINT row_pitch = footprint.Footprint.RowPitch;
for (int y = 0; y < texture->height; ++y) {
memcpy(pixel + y * row_pitch, ((uint8_t *)data) + y * width * format_size, width * format_size);
#ifdef WITH_BC7
if (data != original_data) {
memcpy(pixel, data, ((width + 3) / 4) * ((height + 3) / 4) * 16); // BC7ENC_BLOCK_SIZE
}
else
#endif
{
for (int y = 0; y < texture->height; ++y) {
memcpy(pixel + y * row_pitch, ((uint8_t *)data) + y * width * format_size, width * format_size);
}
}
upload_buffer->lpVtbl->Unmap(upload_buffer, 0, NULL);
@@ -991,6 +1010,12 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
command_list->lpVtbl->ResourceBarrier(command_list, 1, &barrier);
gpu_execute_and_wait(); ////
#ifdef WITH_BC7
if (data != original_data) {
free(data);
}
#endif
}
void gpu_texture_destroy_internal(gpu_texture_t *tex) {
@@ -1136,9 +1161,9 @@ void gpu_constant_buffer_lock(gpu_buffer_t *buffer, int start, int count) {
buffer->impl.last_start = start;
buffer->impl.last_count = count;
D3D12_RANGE range = {
.Begin = start,
.End = start + count,
};
.Begin = start,
.End = start + count,
};
uint8_t *p;
buffer->impl.buffer->lpVtbl->Map(buffer->impl.buffer, 0, &range, (void **)&p);
buffer->data = &p[start];
@@ -1171,6 +1196,20 @@ char *gpu_device_name() {
return device_name;
}
bool gpu_bc7_supported(int width, int height, gpu_texture_format_t format) {
static bool bc7_supported = false;
#ifdef WITH_BC7
static bool bc7_checked = false;
if (!bc7_checked) {
bc7_checked = true;
D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt = {.Format = DXGI_FORMAT_BC7_UNORM};
bc7_supported = SUCCEEDED(device->lpVtbl->CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_SUPPORT, &fmt, sizeof(fmt)));
}
#endif
return bc7_supported && format == GPU_TEXTURE_FORMAT_RGBA32 && width >= 2048 && height >= 2048 && (width & (width - 1)) == 0 &&
(height & (height - 1)) == 0;
}
typedef struct inst {
mat4_t m;
int i;
@@ -1478,12 +1517,12 @@ void gpu_raytrace_acceleration_structure_build(gpu_acceleration_structure_t *acc
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO bottom_level_prebuild_info = {0};
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS inputs = {
.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY,
.NumDescs = 1,
.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL,
.pGeometryDescs = &geometry_descs[i],
.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE,
};
.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY,
.NumDescs = 1,
.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL,
.pGeometryDescs = &geometry_descs[i],
.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE,
};
dxr_device->lpVtbl->GetRaytracingAccelerationStructurePrebuildInfo(dxr_device, &inputs, &bottom_level_prebuild_info);
bottom_level_inputs[i] = inputs;
+64 -32
View File
@@ -378,7 +378,7 @@ void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data) {
// Read buffer
id<MTLBuffer> buffer = (__bridge id<MTLBuffer>)readback_buffer;
memcpy(data, [buffer contents], render_target -> width * render_target -> height *gpu_texture_format_size(render_target->format));
memcpy(data, [buffer contents], render_target->width * render_target->height * gpu_texture_format_size(render_target->format));
}
void gpu_set_constant_buffer(gpu_buffer_t *buffer, int offset, size_t size) {
@@ -543,6 +543,21 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
if (mtlformat == MTLPixelFormatBGRA8Unorm) {
mtlformat = MTLPixelFormatRGBA8Unorm;
}
void *original_data = data;
int bytes_per_row = width * gpu_texture_format_size(format);
int bytes_per_image = bytes_per_row * height;
#ifdef WITH_BC7
if (gpu_bc7_supported(width, height, format)) {
texture->format = GPU_TEXTURE_FORMAT_RGBA32_BC7;
mtlformat = MTLPixelFormatBC7_RGBAUnorm;
data = gpu_bc7_compress(data, width, height);
bytes_per_row = ((width + 3) / 4) * 16; // BC7ENC_BLOCK_SIZE
bytes_per_image = bytes_per_row * ((height + 3) / 4);
}
#endif
MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:mtlformat width:width height:height mipmapped:NO];
descriptor.textureType = MTLTextureType2D;
descriptor.width = width;
@@ -557,15 +572,22 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
id<MTLTexture> tex = [device newTextureWithDescriptor:descriptor];
if (tex == nil) {
gpu_cleanup();
tex = [device newTextureWithDescriptor:descriptor];
#ifdef WITH_BC7
if (data != original_data) {
free(data);
}
#endif
gpu_texture_init_from_bytes(texture, original_data, width, height, format);
return;
}
texture->impl._tex = (__bridge_retained void *)tex;
[tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
mipmapLevel:0
slice:0
withBytes:data
bytesPerRow:width * gpu_texture_format_size(format)
bytesPerImage:width * gpu_texture_format_size(format) * height];
texture->impl._tex = (__bridge_retained void *)tex;
[tex replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 slice:0 withBytes:data bytesPerRow:bytes_per_row bytesPerImage:bytes_per_image];
#ifdef WITH_BC7
if (data != original_data) {
free(data);
}
#endif
}
void gpu_texture_destroy_internal(gpu_texture_t *target) {
@@ -651,33 +673,43 @@ char *gpu_device_name() {
return (char *)[device.name UTF8String];
}
bool gpu_bc7_supported(int width, int height, gpu_texture_format_t format) {
#ifdef WITH_BC7
id<MTLDevice> device = get_metal_device();
return [device supportsBCTextureCompression] && format == GPU_TEXTURE_FORMAT_RGBA32 && width >= 2048 && height >= 2048 && (width & (width - 1)) == 0 &&
(height & (height - 1)) == 0;
#else
return false;
#endif
}
typedef struct inst {
mat4_t m;
int i;
int i;
} inst_t;
static gpu_acceleration_structure_t *accel;
static gpu_raytrace_pipeline_t *pipeline;
static gpu_texture_t *output = NULL;
static gpu_buffer_t *constant_buf;
static id<MTLComputePipelineState> _raytracing_pipeline;
static NSMutableArray *_primitive_accels;
static id<MTLAccelerationStructure> _instance_accel;
static dispatch_semaphore_t _semaphore;
static gpu_texture_t *_texpaint0;
static gpu_texture_t *_texpaint1;
static gpu_texture_t *_texpaint2;
static gpu_texture_t *_texenv;
static gpu_texture_t *_texsobol;
static gpu_texture_t *_texscramble;
static gpu_texture_t *_texrank;
static gpu_buffer_t *vb[16];
static gpu_buffer_t *vb_last[16];
static gpu_buffer_t *ib[16];
static int vb_count = 0;
static int vb_count_last = 0;
static inst_t instances[1024];
static int instances_count = 0;
static gpu_acceleration_structure_t *accel;
static gpu_raytrace_pipeline_t *pipeline;
static gpu_texture_t *output = NULL;
static gpu_buffer_t *constant_buf;
static id<MTLComputePipelineState> _raytracing_pipeline;
static NSMutableArray *_primitive_accels;
static id<MTLAccelerationStructure> _instance_accel;
static dispatch_semaphore_t _semaphore;
static gpu_texture_t *_texpaint0;
static gpu_texture_t *_texpaint1;
static gpu_texture_t *_texpaint2;
static gpu_texture_t *_texenv;
static gpu_texture_t *_texsobol;
static gpu_texture_t *_texscramble;
static gpu_texture_t *_texrank;
static gpu_buffer_t *vb[16];
static gpu_buffer_t *vb_last[16];
static gpu_buffer_t *ib[16];
static int vb_count = 0;
static int vb_count_last = 0;
static inst_t instances[1024];
static int instances_count = 0;
void gpu_raytrace_pipeline_init(gpu_raytrace_pipeline_t *pipeline, void *shader, int ray_shader_size, gpu_buffer_t *constant_buffer) {
id<MTLDevice> device = get_metal_device();
+26 -78
View File
@@ -1613,48 +1613,6 @@ void gpu_shader_destroy(gpu_shader_t *shader) {
shader->impl.source = NULL;
}
#ifdef WITH_BC7
#include <libs/bc7enc.h>
#include <iron_thread.h>
#define BC7_THREAD_COUNT 16
typedef struct {
uint8_t *src;
uint8_t *dst;
int width;
int height;
int blocks_x;
int total_blocks;
volatile int32_t *next_block;
bc7enc_compress_block_params params;
} bc7_thread_params_t;
static void bc7_thread_func(void *arg) {
bc7_thread_params_t *p = (bc7_thread_params_t *)arg;
for (;;) {
int bi = iron_atomic_increment(p->next_block);
if (bi >= p->total_blocks)
break;
int bx = bi % p->blocks_x;
int by = bi / p->blocks_x;
uint8_t block[64];
for (int py = 0; py < 4; py++) {
for (int px = 0; px < 4; px++) {
int sx = bx * 4 + px < p->width ? bx * 4 + px : p->width - 1;
int sy = by * 4 + py < p->height ? by * 4 + py : p->height - 1;
int src_idx = (sy * p->width + sx) * 4;
int dst_idx = (py * 4 + px) * 4;
block[dst_idx + 0] = p->src[src_idx + 0];
block[dst_idx + 1] = p->src[src_idx + 1];
block[dst_idx + 2] = p->src[src_idx + 2];
block[dst_idx + 3] = p->src[src_idx + 3];
}
}
bc7enc_compress_block(p->dst + (size_t)bi * BC7ENC_BLOCK_SIZE, block, &p->params);
}
}
#endif
void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) {
texture->width = width;
texture->height = height;
@@ -1671,40 +1629,11 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
void *original_data = data;
#ifdef WITH_BC7
void *bc7_data = NULL;
if (format == GPU_TEXTURE_FORMAT_RGBA32 && width >= 2048 && height >= 2048) {
vk_format = VK_FORMAT_BC7_UNORM_BLOCK;
int blocks_x = (width + 3) / 4;
int blocks_y = (height + 3) / 4;
bc7_data = malloc(blocks_x * blocks_y * BC7ENC_BLOCK_SIZE);
static bc7enc_bool bc7enc_ready = BC7ENC_FALSE;
if (!bc7enc_ready) {
bc7enc_compress_block_init();
bc7enc_ready = BC7ENC_TRUE;
}
volatile int32_t next_block = 0;
bc7_thread_params_t tp = {
.src = (uint8_t *)data,
.dst = (uint8_t *)bc7_data,
.width = width,
.height = height,
.blocks_x = blocks_x,
.total_blocks = blocks_x * blocks_y,
.next_block = &next_block,
};
bc7enc_compress_block_params_init(&tp.params);
tp.params.m_max_partitions_mode = 0;
tp.params.m_try_least_squares = false;
iron_thread_t threads[BC7_THREAD_COUNT];
for (int i = 0; i < BC7_THREAD_COUNT; i++) {
iron_thread_init(&threads[i], bc7_thread_func, &tp);
}
for (int i = 0; i < BC7_THREAD_COUNT; i++) {
iron_thread_wait_and_destroy(&threads[i]);
}
data = bc7_data;
_upload_size = (VkDeviceSize)((width + 3) / 4) * ((height + 3) / 4) * BC7ENC_BLOCK_SIZE;
if (gpu_bc7_supported(width, height, format)) {
texture->format = GPU_TEXTURE_FORMAT_RGBA32_BC7;
vk_format = VK_FORMAT_BC7_UNORM_BLOCK;
data = gpu_bc7_compress(data, width, height);
_upload_size = (VkDeviceSize)((width + 3) / 4) * ((height + 3) / 4) * 16; // BC7ENC_BLOCK_SIZE
}
#endif
@@ -1773,7 +1702,9 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
gpu_cleanup_internal();
gpu_cleanup();
#ifdef WITH_BC7
free(bc7_data);
if (data != original_data) {
free(data);
}
#endif
gpu_texture_init_from_bytes(texture, original_data, width, height, format);
return;
@@ -1846,7 +1777,9 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
gpu_execute_and_wait(); ////
#ifdef WITH_BC7
free(bc7_data);
if (data != original_data) {
free(data);
}
#endif
}
@@ -1999,6 +1932,21 @@ char *gpu_device_name() {
return device_name;
}
bool gpu_bc7_supported(int width, int height, gpu_texture_format_t format) {
static bool bc7_supported = false;
#ifdef WITH_BC7
static bool bc7_checked = false;
if (!bc7_checked) {
bc7_checked = true;
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(gpu, VK_FORMAT_BC7_UNORM_BLOCK, &props);
bc7_supported = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0;
}
#endif
return bc7_supported && format == GPU_TEXTURE_FORMAT_RGBA32 && width >= 2048 && height >= 2048 && (width & (width - 1)) == 0 &&
(height & (height - 1)) == 0;
}
typedef struct inst {
mat4_t m;
int i;
+1
View File
@@ -1212,4 +1212,5 @@ IMPORT("wgpuSurfaceConfigure") void wgpuSurfaceConfigure(WGPUSurface surface, WG
IMPORT("wgpuInstanceRequestAdapterSync") WGPUAdapter wgpuInstanceRequestAdapterSync();
IMPORT("wgpuAdapterRequestDeviceSync") WGPUDevice wgpuAdapterRequestDeviceSync();
IMPORT("wgpuDeviceHasFeature") WGPUBool wgpuDeviceHasFeature(WGPUDevice device, WGPUFeatureName feature);
IMPORT("wgpuBufferUnmap2") void wgpuBufferUnmap2(WGPUBuffer buffer, void *data, int start, int count);
+47 -14
View File
@@ -135,9 +135,9 @@ static void create_descriptors(void) {
};
descriptor_layout = wgpuDeviceCreateBindGroupLayout(device, &layout_create_info);
bindings[1].sampler.type = WGPUSamplerBindingType_NonFiltering;
bindings[1].sampler.type = WGPUSamplerBindingType_NonFiltering;
bindings[2].texture.sampleType = WGPUTextureSampleType_UnfilterableFloat;
descriptor_layout_depth = wgpuDeviceCreateBindGroupLayout(device, &layout_create_info);
descriptor_layout_depth = wgpuDeviceCreateBindGroupLayout(device, &layout_create_info);
WGPUTextureDescriptor dummy_desc = {
.size = {1, 1, 1},
@@ -318,10 +318,10 @@ void gpu_begin_internal(gpu_clear_t flags, unsigned color, float depth) {
wgpuSurfaceGetCurrentTexture(surface, &surface_texture);
framebuffers[0].impl.texture = surface_texture.texture;
WGPUTextureViewDescriptor view_info = {
.dimension = WGPUTextureViewDimension_2D,
.format = WGPUTextureFormat_RGBA8Unorm,
.mipLevelCount = 1,
.arrayLayerCount = 1,
.dimension = WGPUTextureViewDimension_2D,
.format = WGPUTextureFormat_RGBA8Unorm,
.mipLevelCount = 1,
.arrayLayerCount = 1,
};
framebuffers[0].impl.view = wgpuTextureCreateView(surface_texture.texture, &view_info);
framebuffers[0].width = width;
@@ -531,7 +531,7 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
pipeline->impl.pipeline_layout = wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_create_info);
pipeline_layout_create_info.bindGroupLayouts = &descriptor_layout_depth;
pipeline->impl.pipeline_layout_depth = wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_create_info);
pipeline->impl.pipeline_layout_depth = wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_create_info);
WGPURenderPipelineDescriptor pipeline_desc = {0};
pipeline_desc.layout = pipeline->impl.pipeline_layout;
@@ -625,7 +625,7 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
pipeline->impl.pipeline = wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
pipeline_desc.layout = pipeline->impl.pipeline_layout_depth;
pipeline_desc.layout = pipeline->impl.pipeline_layout_depth;
pipeline->impl.pipeline_depth = wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
wgpuShaderModuleRelease(pipeline_desc.vertex.module);
@@ -650,12 +650,29 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
texture->format = format;
texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE;
WGPUTextureFormat wgpu_format = convert_image_format(format);
int bpp = gpu_texture_format_size(format);
int aligned_bpr = bytes_per_row_align(width * bpp);
size_t upload_size = width * height * bpp;
void *upload_data = data;
WGPUTextureFormat wgpu_format = convert_image_format(format);
int bpp = gpu_texture_format_size(format);
void *original_data = data;
#ifdef WITH_BC7
if (gpu_bc7_supported(width, height, format)) {
texture->format = GPU_TEXTURE_FORMAT_RGBA32_BC7;
wgpu_format = WGPUTextureFormat_BC7RGBAUnorm;
data = gpu_bc7_compress(data, width, height);
}
#endif
int aligned_bpr = bytes_per_row_align(width * bpp);
size_t upload_size = width * height * bpp;
void *upload_data = data;
#ifdef WITH_BC7
if (data != original_data) {
aligned_bpr = ((width + 3) / 4) * 16; // BC7ENC_BLOCK_SIZE
upload_size = (size_t)aligned_bpr * ((height + 3) / 4);
}
else
#endif
if (aligned_bpr != width * bpp) {
upload_size = (size_t)aligned_bpr * height;
upload_data = malloc(upload_size);
@@ -685,6 +702,11 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
if (upload_data != data) {
free(upload_data);
}
#ifdef WITH_BC7
if (data != original_data) {
free(data);
}
#endif
WGPUTextureDescriptor image_info = {
.size = {(uint32_t)width, (uint32_t)height, 1},
@@ -800,7 +822,18 @@ char *gpu_device_name() {
return device_name;
}
bool gpu_raytrace_supported(void) { return false; }
bool gpu_bc7_supported(int width, int height, gpu_texture_format_t format) {
bool bc7_supported = false;
#ifdef WITH_BC7
bc7_supported = wgpuDeviceHasFeature(device, WGPUFeatureName_TextureCompressionBC);
#endif
return bc7_supported && format == GPU_TEXTURE_FORMAT_RGBA32 && width >= 2048 && height >= 2048 && (width & (width - 1)) == 0 &&
(height & (height - 1)) == 0;
}
bool gpu_raytrace_supported(void) {
return false;
}
void gpu_raytrace_pipeline_init(gpu_raytrace_pipeline_t *pipeline, void *shader, int shader_size, gpu_buffer_t *constant_buffer) {}
void gpu_raytrace_pipeline_destroy(gpu_raytrace_pipeline_t *pipeline) {}
void gpu_raytrace_acceleration_structure_init(gpu_acceleration_structure_t *accel) {}