Add gpu_use_linear_sampling

This commit is contained in:
luboslenco
2025-08-09 21:20:37 +02:00
parent b179d4baa1
commit a412ca8e1c
6 changed files with 113 additions and 85 deletions
+19 -14
View File
@@ -266,18 +266,7 @@ void gpu_render_target_init2(gpu_texture_t *render_target, int width, int height
device->lpVtbl->CreateShaderResourceView(device, render_target->impl.image, &srv_desc, handle);
}
void gpu_init_internal(int depth_buffer_bits, bool vsync) {
window_vsync = vsync;
#ifdef _DEBUG
ID3D12Debug *debug_controller = NULL;
if (D3D12GetDebugInterface(&IID_ID3D12Debug, &debug_controller) == S_OK) {
debug_controller->lpVtbl->EnableDebugLayer(debug_controller);
}
#endif
D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, &device);
// Root signature
void create_root_signature(bool linear_sampling) {
ID3DBlob *root_blob;
ID3DBlob *error_blob;
D3D12_ROOT_PARAMETER parameters[2] = {};
@@ -299,7 +288,7 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) {
D3D12_STATIC_SAMPLER_DESC samplers[GPU_MAX_TEXTURES];
for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
samplers[i].ShaderRegister = i;
samplers[i].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
samplers[i].Filter = linear_sampling ? D3D12_FILTER_MIN_MAG_MIP_LINEAR : D3D12_FILTER_MIN_MAG_MIP_POINT;
samplers[i].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplers[i].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplers[i].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
@@ -321,12 +310,24 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) {
};
D3D12SerializeRootSignature(&root_signature_desc, D3D_ROOT_SIGNATURE_VERSION_1, &root_blob, &error_blob);
device->lpVtbl->CreateRootSignature(device, 0, root_blob->lpVtbl->GetBufferPointer(root_blob), root_blob->lpVtbl->GetBufferSize(root_blob), &IID_ID3D12RootSignature, &root_signature);
}
void gpu_init_internal(int depth_buffer_bits, bool vsync) {
window_vsync = vsync;
#ifdef _DEBUG
ID3D12Debug *debug_controller = NULL;
if (D3D12GetDebugInterface(&IID_ID3D12Debug, &debug_controller) == S_OK) {
debug_controller->lpVtbl->EnableDebugLayer(debug_controller);
}
#endif
D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, &device);
create_root_signature(true);
D3D12_COMMAND_QUEUE_DESC queue_desc = {
.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
.Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
};
device->lpVtbl->CreateCommandQueue(device, &queue_desc, &IID_ID3D12CommandQueue, &queue);
HWND hwnd = iron_windows_window_handle();
@@ -674,6 +675,10 @@ void gpu_set_texture(int unit, gpu_texture_t *texture) {
current_textures[unit] = texture;
}
void gpu_use_linear_sampling(bool b) {
create_root_signature(b);
}
void gpu_pipeline_destroy(gpu_pipeline_t *pipe) {
if (pipe->impl.pso != NULL) {
pipe->impl.pso->lpVtbl->Release(pipe->impl.pso);
+62 -47
View File
@@ -18,6 +18,7 @@ static id<MTLArgumentEncoder> argument_encoder = nil;
static id<MTLBuffer> argument_buffer = nil;
static id<CAMetalDrawable> drawable;
static id<MTLSamplerState> linear_sampler;
static id<MTLSamplerState> point_sampler;
static int argument_buffer_step;
static gpu_buffer_t *current_vb;
static gpu_buffer_t *current_ib;
@@ -32,6 +33,7 @@ static gpu_texture_t *current_textures[GPU_MAX_TEXTURES] = {
};
static void *readback_buffer;
static int readback_buffer_size = 0;
static bool linear_sampling = true;
static MTLBlendFactor convert_blending_factor(gpu_blending_factor_t factor) {
switch (factor) {
@@ -134,22 +136,31 @@ static void next_drawable() {
void gpu_init_internal(int depth_buffer_bits, bool vsync) {
id<MTLDevice> device = get_metal_device();
MTLSamplerDescriptor *linear_desc = [MTLSamplerDescriptor new];
linear_desc.minFilter = MTLSamplerMinMagFilterLinear;
linear_desc.magFilter = MTLSamplerMinMagFilterLinear;
linear_desc.mipFilter = MTLSamplerMipFilterLinear;
linear_desc.sAddressMode = MTLSamplerAddressModeRepeat;
linear_desc.tAddressMode = MTLSamplerAddressModeRepeat;
MTLSamplerDescriptor *linear_desc = [MTLSamplerDescriptor new];
linear_desc.minFilter = MTLSamplerMinMagFilterLinear;
linear_desc.magFilter = MTLSamplerMinMagFilterLinear;
linear_desc.mipFilter = MTLSamplerMipFilterLinear;
linear_desc.sAddressMode = MTLSamplerAddressModeRepeat;
linear_desc.tAddressMode = MTLSamplerAddressModeRepeat;
linear_desc.supportArgumentBuffers = true;
linear_sampler = [device newSamplerStateWithDescriptor:linear_desc];
MTLSamplerDescriptor *point_desc = [MTLSamplerDescriptor new];
point_desc.minFilter = MTLSamplerMinMagFilterNearest;
point_desc.magFilter = MTLSamplerMinMagFilterNearest;
point_desc.mipFilter = MTLSamplerMipFilterNearest;
point_desc.sAddressMode = MTLSamplerAddressModeRepeat;
point_desc.tAddressMode = MTLSamplerAddressModeRepeat;
point_desc.supportArgumentBuffers = true;
point_sampler = [device newSamplerStateWithDescriptor:point_desc];
MTLArgumentDescriptor *constants_desc = [MTLArgumentDescriptor argumentDescriptor];
constants_desc.dataType = MTLDataTypePointer;
constants_desc.index = 0;
constants_desc.dataType = MTLDataTypePointer;
constants_desc.index = 0;
MTLArgumentDescriptor *sampler_desc = [MTLArgumentDescriptor argumentDescriptor];
sampler_desc.dataType = MTLDataTypeSampler;
sampler_desc.index = 1;
sampler_desc.dataType = MTLDataTypeSampler;
sampler_desc.index = 1;
MTLArgumentDescriptor *texture_desc[GPU_MAX_TEXTURES];
for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
@@ -159,8 +170,8 @@ void gpu_init_internal(int depth_buffer_bits, bool vsync) {
texture_desc[i].textureType = MTLTextureType2D;
}
NSArray *arguments = [NSArray arrayWithObjects:constants_desc, sampler_desc, texture_desc[0], texture_desc[1], texture_desc[2], texture_desc[3], texture_desc[4], texture_desc[5], texture_desc[6], texture_desc[7], texture_desc[8], texture_desc[9], texture_desc[10], texture_desc[11], texture_desc[12], texture_desc[13], texture_desc[14], texture_desc[15], nil];
argument_encoder = [device newArgumentEncoderWithArguments:arguments];
NSArray *arguments = [NSArray arrayWithObjects:constants_desc, sampler_desc, texture_desc[0], texture_desc[1], texture_desc[2], texture_desc[3], texture_desc[4], texture_desc[5], texture_desc[6], texture_desc[7], texture_desc[8], texture_desc[9], texture_desc[10], texture_desc[11], texture_desc[12], texture_desc[13], texture_desc[14], texture_desc[15], nil];
argument_encoder = [device newArgumentEncoderWithArguments:arguments];
argument_buffer_step = [argument_encoder encodedLength];
argument_buffer = [device newBufferWithLength:(argument_buffer_step * GPU_CONSTANT_BUFFER_MULTIPLE) options:MTLResourceStorageModeShared];
@@ -284,10 +295,10 @@ void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after)
void gpu_draw_internal() {
id<MTLBuffer> index_buffer = (__bridge id<MTLBuffer>)current_ib->impl.metal_buffer;
[command_encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:current_ib->count
indexType:MTLIndexTypeUInt32
indexBuffer:index_buffer
indexBufferOffset:0];
indexCount:current_ib->count
indexType:MTLIndexTypeUInt32
indexBuffer:index_buffer
indexBufferOffset:0];
}
void gpu_viewport(int x, int y, int width, int height) {
@@ -364,30 +375,30 @@ void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data) {
id<MTLCommandBuffer> command_buffer = [queue commandBuffer];
id<MTLBlitCommandEncoder> command_encoder = [command_buffer blitCommandEncoder];
[command_encoder copyFromTexture:(__bridge id<MTLTexture>)render_target->impl._tex
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(render_target->width, render_target->height, 1)
toBuffer:(__bridge id<MTLBuffer>)readback_buffer
destinationOffset:0
destinationBytesPerRow:render_target->width * gpu_texture_format_size(render_target->format)
destinationBytesPerImage:0];
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(render_target->width, render_target->height, 1)
toBuffer:(__bridge id<MTLBuffer>)readback_buffer
destinationOffset:0
destinationBytesPerRow:render_target->width * gpu_texture_format_size(render_target->format)
destinationBytesPerImage:0];
[command_encoder endEncoding];
[command_buffer commit];
[command_buffer waitUntilCompleted];
// 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) {
id<MTLBuffer> buf = (__bridge id<MTLBuffer>)buffer->impl.metal_buffer;
[argument_encoder setArgumentBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index];
[argument_encoder setBuffer:buf offset:offset atIndex:0];
[argument_encoder setSamplerState:linear_sampler atIndex:1];
[argument_encoder setSamplerState:(linear_sampling ? linear_sampler : point_sampler) atIndex:1];
[command_encoder setVertexBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index atIndex:1];
[command_encoder setFragmentBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index atIndex:1];
[command_encoder setFragmentBuffer:argument_buffer offset:argument_buffer_step * constant_buffer_index atIndex:1];
[command_encoder useResource:buf usage:MTLResourceUsageRead stages:MTLRenderStageVertex|MTLRenderStageFragment];
for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
if (current_textures[i] == NULL) {
@@ -403,6 +414,10 @@ void gpu_set_texture(int unit, gpu_texture_t *texture) {
current_textures[unit] = texture;
}
void gpu_use_linear_sampling(bool b) {
linear_sampling = b;
}
void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) {
id<MTLRenderPipelineState> pipe = (__bridge_transfer id<MTLRenderPipelineState>)pipeline->impl._pipeline;
pipe = nil;
@@ -434,8 +449,8 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
for (int i = 0; i < pipeline->color_attachment_count; ++i) {
render_pipeline_desc.colorAttachments[i].pixelFormat = convert_texture_format(pipeline->color_attachment[i]);
render_pipeline_desc.colorAttachments[i].blendingEnabled =
pipeline->blend_source != GPU_BLEND_ONE || pipeline->blend_destination != GPU_BLEND_ZERO ||
pipeline->alpha_blend_source != GPU_BLEND_ONE || pipeline->alpha_blend_destination != GPU_BLEND_ZERO;
pipeline->blend_source != GPU_BLEND_ONE || pipeline->blend_destination != GPU_BLEND_ZERO ||
pipeline->alpha_blend_source != GPU_BLEND_ONE || pipeline->alpha_blend_destination != GPU_BLEND_ZERO;
render_pipeline_desc.colorAttachments[i].sourceRGBBlendFactor = convert_blending_factor(pipeline->blend_source);
render_pipeline_desc.colorAttachments[i].destinationRGBBlendFactor = convert_blending_factor(pipeline->blend_destination);
render_pipeline_desc.colorAttachments[i].rgbBlendOperation = MTLBlendOperationAdd;
@@ -443,9 +458,9 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
render_pipeline_desc.colorAttachments[i].destinationAlphaBlendFactor = convert_blending_factor(pipeline->alpha_blend_destination);
render_pipeline_desc.colorAttachments[i].alphaBlendOperation = MTLBlendOperationAdd;
render_pipeline_desc.colorAttachments[i].writeMask =
(pipeline->color_write_mask_red[i] ? MTLColorWriteMaskRed : 0) |
(pipeline->color_write_mask_red[i] ? MTLColorWriteMaskRed : 0) |
(pipeline->color_write_mask_green[i] ? MTLColorWriteMaskGreen : 0) |
(pipeline->color_write_mask_blue[i] ? MTLColorWriteMaskBlue : 0) |
(pipeline->color_write_mask_blue[i] ? MTLColorWriteMaskBlue : 0) |
(pipeline->color_write_mask_alpha[i] ? MTLColorWriteMaskAlpha : 0);
}
render_pipeline_desc.depthAttachmentPixelFormat = pipeline->depth_attachment_bits > 0 ? MTLPixelFormatDepth32Float : MTLPixelFormatInvalid;
@@ -490,9 +505,9 @@ void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
pipeline->impl._pipeline = (__bridge_retained void *)[
device newRenderPipelineStateWithDescriptor:render_pipeline_desc
options:MTLPipelineOptionBufferTypeInfo
reflection:&reflection
error:&errors];
options:MTLPipelineOptionBufferTypeInfo
reflection:&reflection
error:&errors];
MTLDepthStencilDescriptor *depth_descriptor = [MTLDepthStencilDescriptor new];
depth_descriptor.depthCompareFunction = convert_compare_mode(pipeline->depth_mode);
@@ -534,9 +549,9 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
mtlformat = MTLPixelFormatRGBA8Unorm;
}
MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:mtlformat
width:width
height:height
mipmapped:NO];
width:width
height:height
mipmapped:NO];
descriptor.textureType = MTLTextureType2D;
descriptor.width = width;
descriptor.height = height;
@@ -550,11 +565,11 @@ void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width,
id<MTLTexture> tex = [device newTextureWithDescriptor:descriptor];
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];
mipmapLevel:0
slice:0
withBytes:data
bytesPerRow:width * gpu_texture_format_size(format)
bytesPerImage:width * gpu_texture_format_size(format) * height];
}
void gpu_texture_destroy(gpu_texture_t *target) {
@@ -613,8 +628,8 @@ void gpu_index_buffer_init(gpu_buffer_t *buffer, int indexCount) {
options |= MTLResourceStorageModeShared;
buffer->impl.metal_buffer = (__bridge_retained void *)[device
newBufferWithLength:sizeof(uint32_t) * indexCount
options:options];
newBufferWithLength:sizeof(uint32_t) * indexCount
options:options];
}
void gpu_buffer_destroy(gpu_buffer_t *buffer) {
@@ -667,8 +682,8 @@ void gpu_raytrace_pipeline_init(gpu_raytrace_pipeline_t *pipeline, void *ray_sha
NSError *error = nil;
id<MTLLibrary> library = [device newLibraryWithSource:[[NSString alloc] initWithBytes:ray_shader length:ray_shader_size encoding:NSUTF8StringEncoding]
options:nil
error:&error];
options:nil
error:&error];
if (library == nil) {
iron_error("%s", error.localizedDescription.UTF8String);
}
@@ -859,7 +874,7 @@ void gpu_raytrace_dispatch_rays() {
NSUInteger height = output->height;
MTLSize threads_per_threadgroup = MTLSizeMake(8, 8, 1);
MTLSize threadgroups = MTLSizeMake((width + threads_per_threadgroup.width - 1) / threads_per_threadgroup.width,
(height + threads_per_threadgroup.height - 1) / threads_per_threadgroup.height, 1);
(height + threads_per_threadgroup.height - 1) / threads_per_threadgroup.height, 1);
id<MTLComputeCommandEncoder> compute_encoder = [command_buffer computeCommandEncoder];
[compute_encoder setBuffer:(__bridge id<MTLBuffer>)constant_buf->impl.metal_buffer offset:0 atIndex:0];
+29 -22
View File
@@ -36,7 +36,7 @@ static VkRenderingInfo current_rendering_info;
static VkRenderingAttachmentInfo current_color_attachment_infos[8];
static VkRenderingAttachmentInfo current_depth_attachment_info;
static VkPhysicalDeviceMemoryProperties memory_properties;
static VkSampler immutable_sampler;
static VkSampler current_sampler;
static VkCommandBuffer command_buffer;
static VkBuffer buffers_to_destroy[256];
static VkDeviceMemory buffer_memories_to_destroy[256];
@@ -285,6 +285,28 @@ static void set_image_layout(VkImage image, VkImageAspectFlags aspect_mask, VkIm
}
}
static void create_sampler(bool linear_sampling) {
VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = linear_sampling ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.minFilter = linear_sampling ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.anisotropyEnable = VK_FALSE,
.maxAnisotropy = 1.0f,
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
.unnormalizedCoordinates = VK_FALSE,
.compareEnable = VK_FALSE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.mipmapMode = linear_sampling ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
.mipLodBias = 0.0f,
.minLod = 0.0f,
.maxLod = 0.0f,
};
vkCreateSampler(device, &sampler_info, NULL, &current_sampler);
}
static void create_descriptors(void) {
VkDescriptorSetLayoutBinding bindings[18];
memset(bindings, 0, sizeof(bindings));
@@ -295,31 +317,12 @@ static void create_descriptors(void) {
bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
bindings[0].pImmutableSamplers = NULL;
VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = VK_FILTER_LINEAR,
.minFilter = VK_FILTER_LINEAR,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.anisotropyEnable = VK_FALSE,
.maxAnisotropy = 1.0f,
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
.unnormalizedCoordinates = VK_FALSE,
.compareEnable = VK_FALSE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.mipLodBias = 0.0f,
.minLod = 0.0f,
.maxLod = 0.0f,
};
vkCreateSampler(device, &sampler_info, NULL, &immutable_sampler);
create_sampler(true);
bindings[1].binding = 1;
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
bindings[1].descriptorCount = 1;
bindings[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
bindings[1].pImmutableSamplers = &immutable_sampler;
bindings[1].pImmutableSamplers = &current_sampler;
for (int i = 2; i < 2 + GPU_MAX_TEXTURES; ++i) {
bindings[i].binding = i;
@@ -1437,6 +1440,10 @@ void gpu_set_texture(int unit, gpu_texture_t *texture) {
current_textures[unit] = texture;
}
void gpu_use_linear_sampling(bool b) {
create_sampler(b);
}
void gpu_pipeline_destroy(gpu_pipeline_t *pipeline) {
vkDestroyPipeline(device, pipeline->impl.pipeline, NULL);
vkDestroyPipelineLayout(device, pipeline->impl.pipeline_layout, NULL);
+1
View File
@@ -206,6 +206,7 @@ void gpu_set_index_buffer(gpu_buffer_t *buffer);
void gpu_set_constant_buffer(gpu_buffer_t *buffer, int offset, size_t size);
void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data);
void gpu_set_texture(int unit, gpu_texture_t *texture);
void gpu_use_linear_sampling(bool b);
bool gpu_raytrace_supported(void);
void gpu_raytrace_pipeline_init(gpu_raytrace_pipeline_t *pipeline, void *ray_shader, int ray_shader_size, gpu_buffer_t *constant_buffer);
+1
View File
@@ -248,6 +248,7 @@ declare function gpu_set_float4(location: i32, value1: f32, value2: f32, value3:
declare function gpu_set_floats(location: i32, values: f32_array_t): void;
declare function gpu_set_matrix4(location: i32, matrix: mat4_t): void;
declare function gpu_set_matrix3(location: i32, matrix: mat3_t): void;
declare function gpu_use_linear_sampling(b: bool): void;
declare function iron_time(): f32;
declare function iron_window_width(): i32;
+1 -2
View File
@@ -407,8 +407,7 @@ function ui_menubar_draw_category_items(ui: ui_t) {
}
context_raw.texture_filter = ui_check(filter_handle, " " + tr("Filter Textures"));
if (filter_handle.changed) {
make_material_parse_paint_material();
make_material_parse_mesh_material();
gpu_use_linear_sampling(context_raw.texture_filter);
}
///if is_paint