base: bc7 support
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
Reference in New Issue
Block a user