diff --git a/base/sources/backends/direct3d12_gpu.c b/base/sources/backends/direct3d12_gpu.c index 8e4de687..02312760 100644 --- a/base/sources/backends/direct3d12_gpu.c +++ b/base/sources/backends/direct3d12_gpu.c @@ -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); diff --git a/base/sources/backends/metal_gpu.m b/base/sources/backends/metal_gpu.m index 04047901..b13d18b3 100644 --- a/base/sources/backends/metal_gpu.m +++ b/base/sources/backends/metal_gpu.m @@ -18,6 +18,7 @@ static id argument_encoder = nil; static id argument_buffer = nil; static id drawable; static id linear_sampler; +static id 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 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 index_buffer = (__bridge id)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 command_buffer = [queue commandBuffer]; id command_encoder = [command_buffer blitCommandEncoder]; [command_encoder copyFromTexture:(__bridge id)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)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)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 buffer = (__bridge id)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 buf = (__bridge id)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 pipe = (__bridge_transfer id)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 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 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 compute_encoder = [command_buffer computeCommandEncoder]; [compute_encoder setBuffer:(__bridge id)constant_buf->impl.metal_buffer offset:0 atIndex:0]; diff --git a/base/sources/backends/vulkan_gpu.c b/base/sources/backends/vulkan_gpu.c index fa17537b..c143ee6a 100644 --- a/base/sources/backends/vulkan_gpu.c +++ b/base/sources/backends/vulkan_gpu.c @@ -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, ¤t_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 = ¤t_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); diff --git a/base/sources/iron_gpu.h b/base/sources/iron_gpu.h index f931de71..661fc69e 100644 --- a/base/sources/iron_gpu.h +++ b/base/sources/iron_gpu.h @@ -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); diff --git a/base/sources/ts/iron/iron.ts b/base/sources/ts/iron/iron.ts index 7b5c19aa..7ba97c77 100644 --- a/base/sources/ts/iron/iron.ts +++ b/base/sources/ts/iron/iron.ts @@ -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; diff --git a/base/sources/ts/ui_menubar.ts b/base/sources/ts/ui_menubar.ts index a7b88c9b..5fcf5d8f 100644 --- a/base/sources/ts/ui_menubar.ts +++ b/base/sources/ts/ui_menubar.ts @@ -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