Compare commits

...

4 Commits

Author SHA1 Message Date
Rafael Kitover
b499c2d58c Fix mem leak and wrong API use in Metal driver
Fix massive texture memory leak and some other things wrong with the
Metal driver as suggested by Claude.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-02 20:04:42 +00:00
Rafael Kitover
e8aa4467f1 build: disable default bundling of dylibs on macOS
Add CMake option `BUNDLE_DYLIBS` defaulting to `OFF` to bundle dynamic
libraries into the `.app` bundle. This was the default behavior for
`Release` previously.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-02 18:30:02 +00:00
Rafael Kitover
40c798ef99 "Claude Code Review workflow" 2025-10-02 14:13:51 +00:00
Rafael Kitover
63894ad3f7 "Claude PR Assistant workflow" 2025-10-02 14:13:51 +00:00
4 changed files with 142 additions and 8 deletions

View File

@@ -0,0 +1,57 @@
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

50
.github/workflows/claude.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
# claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'

View File

@@ -1031,7 +1031,9 @@ if(APPLE)
# bundle dylibs and relink them for releasing .app
# also install translations into the .app
# but only in Release mode
if(CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$")
option(BUNDLE_DYLIBS "Bundle dylibs into .app" OFF)
if(GUNDLE_DYLIBS AND CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$")
add_custom_command(
TARGET visualboyadvance-m POST_BUILD
COMMAND bash ${CMAKE_SOURCE_DIR}/tools/macOS/third_party_libs_tool ./visualboyadvance-m.app

View File

@@ -3,6 +3,7 @@
#import <Cocoa/Cocoa.h>
#include <wx/rawbmp.h>
#include <wx/log.h>
#include "wx/drawing.h"
#include "wx/config/option-id.h"
@@ -92,7 +93,7 @@ void MetalDrawingPanel::CreateMetalView()
metalView.layer.needsDisplayOnBoundsChange = YES;
((CAMetalLayer *)metalView.layer).device = metalView.device;
_device = metalView.device;
_device = [metalView.device retain];
const AAPLVertex quadVertices[] =
{
@@ -131,7 +132,11 @@ void MetalDrawingPanel::CreateMetalView()
NSError *error = NULL;
_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
error:&error];
if (!_pipelineState) {
wxLogError("Failed to create Metal pipeline state: %s", [[error localizedDescription] UTF8String]);
return;
}
_commandQueue = [_device newCommandQueue];
if (OPTION(kDispStretch) == false) {
@@ -186,7 +191,7 @@ id<MTLTexture> MetalDrawingPanel::loadTextureUsingData(void *data)
// Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is
// an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0)
textureDescriptor.pixelFormat = metalView.colorPixelFormat;
textureDescriptor.usage = MTLTextureUsageRenderTarget;
textureDescriptor.usage = MTLTextureUsageShaderRead;
// Set the pixel dimensions of the texture
textureDescriptor.width = width * scale;
@@ -196,8 +201,7 @@ id<MTLTexture> MetalDrawingPanel::loadTextureUsingData(void *data)
id<MTLTexture> texture = [_device newTextureWithDescriptor:textureDescriptor];
// Calculate the number of bytes per row in the image.
NSUInteger bytesPerRow = 0;
bytesPerRow = std::ceil((width * scale * 4) + 4);
NSUInteger bytesPerRow = std::ceil(width * scale * 4) + 4;
MTLRegion region = {
{ 0, 0, 0 }, // MTLOrigin
@@ -305,6 +309,10 @@ void MetalDrawingPanel::DrawArea()
src_pos += 4;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
@@ -339,6 +347,10 @@ void MetalDrawingPanel::DrawArea()
src_pos += 2;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
@@ -364,12 +376,20 @@ void MetalDrawingPanel::DrawArea()
pos += 4;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
free(dst);
}
} else {
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(todraw + srcPitch);
}
@@ -382,6 +402,9 @@ void MetalDrawingPanel::DrawArea()
if(renderPassDescriptor != nil)
{
// Cache the drawable to avoid potential race condition
id<CAMetalDrawable> currentDrawable = metalView.currentDrawable;
renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyRenderEncoder";
@@ -410,8 +433,10 @@ void MetalDrawingPanel::DrawArea()
[renderEncoder endEncoding];
// Schedule a present once the framebuffer is complete using the next drawable
[commandBuffer presentDrawable:metalView.currentDrawable];
// Schedule a present once the framebuffer is complete using the cached drawable
if (currentDrawable) {
[commandBuffer presentDrawable:currentDrawable];
}
}
// Finalize rendering here & push the command buffer to the GPU