{"action":"created","comment":{"url":"https://api.github.com/repos/gfx-rs/gfx/pulls/comments/77561433","id":77561433,"diff_hunk":"@@ -0,0 +1,386 @@\n+\n+use spirv_utils::{self, desc, instruction};\n+use core;\n+use core::shade::{self, BaseType, ContainerType, TextureType};\n+\n+#[derive(Clone, Debug, Eq, Hash, PartialEq)]\n+pub struct Variable {\n+    id: desc::Id,\n+    name: String,\n+    ty: desc::Id,\n+    storage_class: desc::StorageClass,\n+    decoration: Vec<instruction::Decoration>,\n+}\n+\n+#[derive(Clone, Debug, Eq, Hash, PartialEq)]\n+pub struct EntryPoint {\n+    name: String,\n+    stage: shade::Stage,\n+    interface: Box<[desc::Id]>,\n+}\n+\n+#[derive(Clone, Debug, Eq, Hash, PartialEq)]\n+pub enum Ty {\n+    Basic(BaseType, ContainerType),\n+    Image(BaseType, TextureType),\n+    Struct(Vec<Type>),\n+    Sampler,\n+}\n+\n+#[derive(Clone, Debug, Eq, Hash, PartialEq)]\n+pub struct Type {\n+    id: desc::Id,\n+    ty: Ty,\n+    decoration: Vec<instruction::Decoration>,\n+}\n+\n+fn map_execution_model_to_stage(model: desc::ExecutionModel) -> Option<shade::Stage> {\n+    use spirv_utils::desc::ExecutionModel::*;\n+    match model {\n+        Vertex => Some(shade::Stage::Vertex),\n+        Geometry => Some(shade::Stage::Geometry),\n+        Fragment => Some(shade::Stage::Pixel),\n+\n+        _ => None,\n+    }\n+}\n+\n+fn map_name_by_id<'a>(module: &'a spirv_utils::RawModule, id: desc::Id) -> Option<&'a str> {\n+    module.uses(id).filter_map(|instr| {\n+        match *instr {\n+            instruction::Instruction::Name { ref name, .. } => {\n+                Some(&name[..])\n+            },\n+            _ => None,\n+        }\n+    }).next()\n+}\n+\n+fn map_member_name_by_id<'a>(module: &'a spirv_utils::RawModule, id: desc::Id, member_id: u32) -> Option<&'a str> {\n+    module.uses(id).filter_map(|instr| {\n+        match *instr {\n+            instruction::Instruction::MemberName { ref name, member, .. } if member == member_id => {\n+                Some(&name[..])\n+            },\n+            _ => None,\n+        }\n+    }).next()\n+}\n+\n+fn map_decorations_by_id(module: &spirv_utils::RawModule, id: desc::Id) -> Vec<instruction::Decoration> {\n+    module.uses(id).filter_map(|instr| {\n+        match *instr {\n+            instruction::Instruction::Decorate { ref decoration, .. } => {\n+                Some(decoration.clone())\n+            },\n+            // TODO: GroupDecorations\n+            _ => None,\n+        }\n+    }).collect::<Vec<_>>()\n+}\n+\n+fn map_member_decorations_by_id(module: &spirv_utils::RawModule, id: desc::Id, member_id: u32) -> Vec<instruction::Decoration> {\n+    module.uses(id).filter_map(|instr| {\n+        match *instr {\n+            instruction::Instruction::MemberDecorate { ref decoration, member, .. } if member == member_id => {\n+                Some(decoration.clone())\n+            },\n+            // TODO: GroupDecorations\n+            _ => None,\n+        }\n+    }).collect::<Vec<_>>()\n+}\n+\n+fn map_image_to_texture_type(dim: desc::Dim, arrayed: bool, multisampled: bool) -> TextureType {\n+    use spirv_utils::desc::Dim;\n+    let arrayed = if arrayed { shade::IsArray::Array } else { shade::IsArray::NoArray };\n+    let multisampled = if multisampled { shade::IsMultiSample::MultiSample } else { shade::IsMultiSample::NoMultiSample };\n+    match dim {\n+        Dim::_1D => shade::TextureType::D1(arrayed),\n+        Dim::_2D => shade::TextureType::D2(arrayed, multisampled),\n+        Dim::_3D => shade::TextureType::D3,\n+        Dim::Cube => shade::TextureType::Cube(arrayed),\n+        Dim::Buffer => shade::TextureType::Buffer,\n+\n+        _ => unimplemented!(),\n+    }\n+}\n+\n+fn map_scalar_to_basetype(instr: &instruction::Instruction) -> Option<BaseType> {\n+    use spirv_utils::instruction::Instruction;\n+    match *instr {\n+        Instruction::TypeBool { .. } => Some(BaseType::Bool),\n+        Instruction::TypeInt { width: 32, signed: false, .. } => Some(BaseType::U32),\n+        Instruction::TypeInt { width: 32, signed: true, .. } => Some(BaseType::I32),\n+        Instruction::TypeFloat { width: 32, ..} => Some(BaseType::F32),\n+        Instruction::TypeFloat { width: 64, ..} => Some(BaseType::F64),\n+\n+        _ => None,\n+    }\n+}\n+\n+fn map_instruction_to_type(module: &spirv_utils::RawModule, instr: &instruction::Instruction) -> Option<Type> {\n+    use spirv_utils::instruction::{Decoration, Instruction};\n+    let id_ty = match *instr {\n+        Instruction::TypeBool { result_type } => {\n+            Some((result_type, Ty::Basic(BaseType::Bool, ContainerType::Single)))\n+        },\n+        Instruction::TypeInt { result_type, width: 32, signed: false } => {\n+            Some((result_type, Ty::Basic(BaseType::U32, ContainerType::Single)))\n+        },\n+        Instruction::TypeInt { result_type, width: 32, signed: true } => {\n+            Some((result_type, Ty::Basic(BaseType::I32, ContainerType::Single)))\n+        },\n+        Instruction::TypeFloat { result_type, width: 32 } => {\n+            Some((result_type, Ty::Basic(BaseType::F32, ContainerType::Single)))\n+        },\n+        Instruction::TypeFloat { result_type, width: 64 } => {\n+            Some((result_type, Ty::Basic(BaseType::F64, ContainerType::Single)))\n+        },\n+        Instruction::TypeVector { result_type, type_id, len } => {\n+            let comp_ty = module.def(type_id).unwrap();\n+            Some((result_type, Ty::Basic(map_scalar_to_basetype(comp_ty).unwrap(), ContainerType::Vector(len as u8))))\n+        },\n+        Instruction::TypeMatrix { result_type, type_id, cols } => {\n+            let (base, rows) = match *module.def(type_id).unwrap() {\n+                Instruction::TypeVector { type_id, len, .. } => {\n+                    let comp_ty = module.def(type_id).unwrap();\n+                    (map_scalar_to_basetype(comp_ty).unwrap(), len)\n+                },\n+                _ => unreachable!(), // SPIR-V module would be invalid\n+            };\n+\n+            let decoration = map_decorations_by_id(&module, result_type.into());\n+\n+            // NOTE: temporary value, changes might be needed later depending on the decorations of the variable\n+            let matrix_format = if decoration.iter().find(|deco| **deco == Decoration::RowMajor).is_some() {\n+                shade::MatrixFormat::RowMajor\n+            } else {\n+                shade::MatrixFormat::ColumnMajor\n+            };\n+\n+            Some((result_type, Ty::Basic(base, ContainerType::Matrix(matrix_format, rows as u8, cols as u8))))\n+        },\n+        Instruction::TypeStruct { result_type, ref fields } => {\n+            Some((\n+                result_type,\n+                Ty::Struct(\n+                    fields.iter().filter_map(|field| // TODO: should be `map()`, currently to ignore unsupported types\n+                        map_instruction_to_type(module, module.def(*field).unwrap())\n+                    ).collect::<Vec<_>>()\n+                )\n+            ))\n+        },\n+        Instruction::TypeSampler { result_type } => {\n+            Some((result_type, Ty::Sampler))\n+        },\n+        Instruction::TypeImage { result_type, type_id, dim, arrayed, multisampled, .. } => {\n+            Some((result_type, Ty::Image(map_scalar_to_basetype(module.def(type_id).unwrap()).unwrap(), map_image_to_texture_type(dim, arrayed, multisampled))))\n+        },\n+\n+        _ => None,\n+    };\n+\n+    if let Some((id, ty)) = id_ty {\n+        Some(Type {\n+            id: id.into(),\n+            ty: ty,\n+            decoration: map_decorations_by_id(&module, id.into()),\n+        })\n+    } else {\n+        None\n+    }\n+}\n+\n+#[derive(Clone, Debug, Eq, Hash, PartialEq)]\n+pub struct SpirvReflection {\n+    entry_points: Vec<EntryPoint>,\n+    variables: Vec<Variable>,\n+    types: Vec<Type>,\n+}\n+\n+pub fn reflect_spirv_module(code: &[u8]) -> SpirvReflection {\n+    use spirv_utils::instruction::Instruction;\n+\n+    let module = spirv_utils::RawModule::read_module(code).unwrap();\n+\n+    let mut entry_points = Vec::new();\n+    let mut variables = Vec::new();\n+    let mut types = Vec::new();\n+    for instr in module.instructions() {\n+        match *instr {\n+            Instruction::EntryPoint { execution_model, ref name, ref interface, .. } => {\n+                if let Some(stage) = map_execution_model_to_stage(execution_model) {\n+                    entry_points.push(EntryPoint {\n+                        name: name.clone(),\n+                        stage: stage,\n+                        interface: interface.clone(),\n+                    });\n+                }\n+            },\n+            Instruction::Variable { result_type, result_id, storage_class, .. } => {\n+                let decoration = map_decorations_by_id(&module, result_id.into());\n+                let ty = {\n+                    // remove indirection layer as the type of every variable is a OpTypePointer\n+                    let ptr_ty = module.def::<desc::TypeId>(result_type.into()).unwrap();\n+                    match *ptr_ty {\n+                        Instruction::TypePointer { ref pointee, .. } => *pointee,\n+                        _ => unreachable!(), // SPIR-V module would be invalid\n+                    }\n+                };\n+\n+                // Every variable MUST have an name annotation\n+                // `glslang` seems to emit empty strings for uniforms with struct type,\n+                // therefore we need to retrieve the name from the struct decl\n+                let name = {\n+                    let name = map_name_by_id(&module, result_id.into()).unwrap();\n+                    if name.is_empty() {\n+                        map_name_by_id(&module, ty.into()).unwrap()\n+                    } else {\n+                        name\n+                    }\n+                };\n+\n+                variables.push(Variable {\n+                    id: result_id.into(),\n+                    name: name.into(),\n+                    ty: ty.into(),\n+                    storage_class: storage_class,\n+                    decoration: decoration,\n+                });\n+            },\n+\n+            _ => {\n+                // Reflect types\n+                if let Some(ty) = map_instruction_to_type(&module, instr) {\n+                    types.push(ty);\n+                }\n+            },\n+        }\n+    }\n+\n+    SpirvReflection {\n+        entry_points: entry_points,\n+        variables: variables,\n+        types: types,\n+    }\n+}\n+\n+pub fn populate_info(info: &mut shade::ProgramInfo, stage: shade::Stage, reflection: &SpirvReflection) {\n+    if stage == shade::Stage::Vertex {\n+        // record vertex attributes\n+        if let Some(entry_point) = reflection.entry_points.iter().find(|ep| ep.name == \"main\" && ep.stage == stage) {\n+            for attrib in entry_point.interface.iter() {\n+                if let Some(var) = reflection.variables.iter().find(|var| var.id == *attrib && var.storage_class == desc::StorageClass::Input) {\n+                    let attrib_name = var.name.clone();\n+                    let slot = var.decoration.iter().filter_map(|dec| match *dec {\n+                                    instruction::Decoration::Location(slot) => Some(slot),\n+                                    _ => None,\n+                                }).next().expect(\"Missing location decoration\");","path":"src/backend/vulkan/src/mirror.rs","position":278,"original_position":279,"commit_id":"7fa00bac9aff93d98d590493f2ee83c7c3b05fb2","original_commit_id":"78edff31bbfddc50ee55771aa7d7fae5fa513c57","user":{"login":"kvark","id":107301,"avatar_url":"https://avatars.githubusercontent.com/u/107301?v=3","gravatar_id":"","url":"https://api.github.com/users/kvark","html_url":"https://github.com/kvark","followers_url":"https://api.github.com/users/kvark/followers","following_url":"https://api.github.com/users/kvark/following{/other_user}","gists_url":"https://api.github.com/users/kvark/gists{/gist_id}","starred_url":"https://api.github.com/users/kvark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kvark/subscriptions","organizations_url":"https://api.github.com/users/kvark/orgs","repos_url":"https://api.github.com/users/kvark/repos","events_url":"https://api.github.com/users/kvark/events{/privacy}","received_events_url":"https://api.github.com/users/kvark/received_events","type":"User","site_admin":false},"body":"I see. It's a minor thing, but I think `find` expresses your intent better.","created_at":"2016-09-06T00:54:17Z","updated_at":"2016-09-06T00:54:17Z","html_url":"https://github.com/gfx-rs/gfx/pull/1037#discussion_r77561433","pull_request_url":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037","_links":{"self":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/comments/77561433"},"html":{"href":"https://github.com/gfx-rs/gfx/pull/1037#discussion_r77561433"},"pull_request":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037"}}},"pull_request":{"url":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037","id":83987062,"html_url":"https://github.com/gfx-rs/gfx/pull/1037","diff_url":"https://github.com/gfx-rs/gfx/pull/1037.diff","patch_url":"https://github.com/gfx-rs/gfx/pull/1037.patch","issue_url":"https://api.github.com/repos/gfx-rs/gfx/issues/1037","number":1037,"state":"open","locked":false,"title":"Vulkan shader reflection","user":{"login":"msiglreith","id":7253845,"avatar_url":"https://avatars.githubusercontent.com/u/7253845?v=3","gravatar_id":"","url":"https://api.github.com/users/msiglreith","html_url":"https://github.com/msiglreith","followers_url":"https://api.github.com/users/msiglreith/followers","following_url":"https://api.github.com/users/msiglreith/following{/other_user}","gists_url":"https://api.github.com/users/msiglreith/gists{/gist_id}","starred_url":"https://api.github.com/users/msiglreith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msiglreith/subscriptions","organizations_url":"https://api.github.com/users/msiglreith/orgs","repos_url":"https://api.github.com/users/msiglreith/repos","events_url":"https://api.github.com/users/msiglreith/events{/privacy}","received_events_url":"https://api.github.com/users/msiglreith/received_events","type":"User","site_admin":false},"body":"First steps into reflecting the SPIR-V modules for defining the descriptor set.\r\n\r\nOpen issues:\r\n* Some properties aren't correctly reflected (marked as `TODO`). Are they actually needed?\r\n* The current slot based system might need some tweaks to avoid running out of available slots.\r\n* Using a combination of Texture/Sampler requires some special handling, similiar to dx11: They must be defined separately in the shader (sampler has an additional `_` in the name).\r\n* Error handling should be improved (lots of `unwraps()`)","created_at":"2016-09-05T11:15:59Z","updated_at":"2016-09-06T00:54:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e08d33880d7125b0f779533fb854afc246109eba","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037/commits","review_comments_url":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037/comments","review_comment_url":"https://api.github.com/repos/gfx-rs/gfx/pulls/comments{/number}","comments_url":"https://api.github.com/repos/gfx-rs/gfx/issues/1037/comments","statuses_url":"https://api.github.com/repos/gfx-rs/gfx/statuses/7fa00bac9aff93d98d590493f2ee83c7c3b05fb2","head":{"label":"msiglreith:vk_mirror","ref":"vk_mirror","sha":"7fa00bac9aff93d98d590493f2ee83c7c3b05fb2","user":{"login":"msiglreith","id":7253845,"avatar_url":"https://avatars.githubusercontent.com/u/7253845?v=3","gravatar_id":"","url":"https://api.github.com/users/msiglreith","html_url":"https://github.com/msiglreith","followers_url":"https://api.github.com/users/msiglreith/followers","following_url":"https://api.github.com/users/msiglreith/following{/other_user}","gists_url":"https://api.github.com/users/msiglreith/gists{/gist_id}","starred_url":"https://api.github.com/users/msiglreith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msiglreith/subscriptions","organizations_url":"https://api.github.com/users/msiglreith/orgs","repos_url":"https://api.github.com/users/msiglreith/repos","events_url":"https://api.github.com/users/msiglreith/events{/privacy}","received_events_url":"https://api.github.com/users/msiglreith/received_events","type":"User","site_admin":false},"repo":{"id":64920512,"name":"gfx","full_name":"msiglreith/gfx","owner":{"login":"msiglreith","id":7253845,"avatar_url":"https://avatars.githubusercontent.com/u/7253845?v=3","gravatar_id":"","url":"https://api.github.com/users/msiglreith","html_url":"https://github.com/msiglreith","followers_url":"https://api.github.com/users/msiglreith/followers","following_url":"https://api.github.com/users/msiglreith/following{/other_user}","gists_url":"https://api.github.com/users/msiglreith/gists{/gist_id}","starred_url":"https://api.github.com/users/msiglreith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msiglreith/subscriptions","organizations_url":"https://api.github.com/users/msiglreith/orgs","repos_url":"https://api.github.com/users/msiglreith/repos","events_url":"https://api.github.com/users/msiglreith/events{/privacy}","received_events_url":"https://api.github.com/users/msiglreith/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/msiglreith/gfx","description":"A high-performance, bindless graphics API for Rust.","fork":true,"url":"https://api.github.com/repos/msiglreith/gfx","forks_url":"https://api.github.com/repos/msiglreith/gfx/forks","keys_url":"https://api.github.com/repos/msiglreith/gfx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/msiglreith/gfx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/msiglreith/gfx/teams","hooks_url":"https://api.github.com/repos/msiglreith/gfx/hooks","issue_events_url":"https://api.github.com/repos/msiglreith/gfx/issues/events{/number}","events_url":"https://api.github.com/repos/msiglreith/gfx/events","assignees_url":"https://api.github.com/repos/msiglreith/gfx/assignees{/user}","branches_url":"https://api.github.com/repos/msiglreith/gfx/branches{/branch}","tags_url":"https://api.github.com/repos/msiglreith/gfx/tags","blobs_url":"https://api.github.com/repos/msiglreith/gfx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/msiglreith/gfx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/msiglreith/gfx/git/refs{/sha}","trees_url":"https://api.github.com/repos/msiglreith/gfx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/msiglreith/gfx/statuses/{sha}","languages_url":"https://api.github.com/repos/msiglreith/gfx/languages","stargazers_url":"https://api.github.com/repos/msiglreith/gfx/stargazers","contributors_url":"https://api.github.com/repos/msiglreith/gfx/contributors","subscribers_url":"https://api.github.com/repos/msiglreith/gfx/subscribers","subscription_url":"https://api.github.com/repos/msiglreith/gfx/subscription","commits_url":"https://api.github.com/repos/msiglreith/gfx/commits{/sha}","git_commits_url":"https://api.github.com/repos/msiglreith/gfx/git/commits{/sha}","comments_url":"https://api.github.com/repos/msiglreith/gfx/comments{/number}","issue_comment_url":"https://api.github.com/repos/msiglreith/gfx/issues/comments{/number}","contents_url":"https://api.github.com/repos/msiglreith/gfx/contents/{+path}","compare_url":"https://api.github.com/repos/msiglreith/gfx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/msiglreith/gfx/merges","archive_url":"https://api.github.com/repos/msiglreith/gfx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/msiglreith/gfx/downloads","issues_url":"https://api.github.com/repos/msiglreith/gfx/issues{/number}","pulls_url":"https://api.github.com/repos/msiglreith/gfx/pulls{/number}","milestones_url":"https://api.github.com/repos/msiglreith/gfx/milestones{/number}","notifications_url":"https://api.github.com/repos/msiglreith/gfx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/msiglreith/gfx/labels{/name}","releases_url":"https://api.github.com/repos/msiglreith/gfx/releases{/id}","deployments_url":"https://api.github.com/repos/msiglreith/gfx/deployments","created_at":"2016-08-04T09:12:32Z","updated_at":"2016-08-04T09:12:34Z","pushed_at":"2016-09-05T22:26:39Z","git_url":"git://github.com/msiglreith/gfx.git","ssh_url":"git@github.com:msiglreith/gfx.git","clone_url":"https://github.com/msiglreith/gfx.git","svn_url":"https://github.com/msiglreith/gfx","homepage":"http://gfx-rs.github.io/","size":19525,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"gfx-rs:master","ref":"master","sha":"c49a20dff63346a07d8546613ec96b653f6840fc","user":{"login":"gfx-rs","id":8213174,"avatar_url":"https://avatars.githubusercontent.com/u/8213174?v=3","gravatar_id":"","url":"https://api.github.com/users/gfx-rs","html_url":"https://github.com/gfx-rs","followers_url":"https://api.github.com/users/gfx-rs/followers","following_url":"https://api.github.com/users/gfx-rs/following{/other_user}","gists_url":"https://api.github.com/users/gfx-rs/gists{/gist_id}","starred_url":"https://api.github.com/users/gfx-rs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gfx-rs/subscriptions","organizations_url":"https://api.github.com/users/gfx-rs/orgs","repos_url":"https://api.github.com/users/gfx-rs/repos","events_url":"https://api.github.com/users/gfx-rs/events{/privacy}","received_events_url":"https://api.github.com/users/gfx-rs/received_events","type":"Organization","site_admin":false},"repo":{"id":13847975,"name":"gfx","full_name":"gfx-rs/gfx","owner":{"login":"gfx-rs","id":8213174,"avatar_url":"https://avatars.githubusercontent.com/u/8213174?v=3","gravatar_id":"","url":"https://api.github.com/users/gfx-rs","html_url":"https://github.com/gfx-rs","followers_url":"https://api.github.com/users/gfx-rs/followers","following_url":"https://api.github.com/users/gfx-rs/following{/other_user}","gists_url":"https://api.github.com/users/gfx-rs/gists{/gist_id}","starred_url":"https://api.github.com/users/gfx-rs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gfx-rs/subscriptions","organizations_url":"https://api.github.com/users/gfx-rs/orgs","repos_url":"https://api.github.com/users/gfx-rs/repos","events_url":"https://api.github.com/users/gfx-rs/events{/privacy}","received_events_url":"https://api.github.com/users/gfx-rs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/gfx-rs/gfx","description":"A high-performance, bindless graphics API for Rust.","fork":false,"url":"https://api.github.com/repos/gfx-rs/gfx","forks_url":"https://api.github.com/repos/gfx-rs/gfx/forks","keys_url":"https://api.github.com/repos/gfx-rs/gfx/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gfx-rs/gfx/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gfx-rs/gfx/teams","hooks_url":"https://api.github.com/repos/gfx-rs/gfx/hooks","issue_events_url":"https://api.github.com/repos/gfx-rs/gfx/issues/events{/number}","events_url":"https://api.github.com/repos/gfx-rs/gfx/events","assignees_url":"https://api.github.com/repos/gfx-rs/gfx/assignees{/user}","branches_url":"https://api.github.com/repos/gfx-rs/gfx/branches{/branch}","tags_url":"https://api.github.com/repos/gfx-rs/gfx/tags","blobs_url":"https://api.github.com/repos/gfx-rs/gfx/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gfx-rs/gfx/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gfx-rs/gfx/git/refs{/sha}","trees_url":"https://api.github.com/repos/gfx-rs/gfx/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gfx-rs/gfx/statuses/{sha}","languages_url":"https://api.github.com/repos/gfx-rs/gfx/languages","stargazers_url":"https://api.github.com/repos/gfx-rs/gfx/stargazers","contributors_url":"https://api.github.com/repos/gfx-rs/gfx/contributors","subscribers_url":"https://api.github.com/repos/gfx-rs/gfx/subscribers","subscription_url":"https://api.github.com/repos/gfx-rs/gfx/subscription","commits_url":"https://api.github.com/repos/gfx-rs/gfx/commits{/sha}","git_commits_url":"https://api.github.com/repos/gfx-rs/gfx/git/commits{/sha}","comments_url":"https://api.github.com/repos/gfx-rs/gfx/comments{/number}","issue_comment_url":"https://api.github.com/repos/gfx-rs/gfx/issues/comments{/number}","contents_url":"https://api.github.com/repos/gfx-rs/gfx/contents/{+path}","compare_url":"https://api.github.com/repos/gfx-rs/gfx/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gfx-rs/gfx/merges","archive_url":"https://api.github.com/repos/gfx-rs/gfx/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gfx-rs/gfx/downloads","issues_url":"https://api.github.com/repos/gfx-rs/gfx/issues{/number}","pulls_url":"https://api.github.com/repos/gfx-rs/gfx/pulls{/number}","milestones_url":"https://api.github.com/repos/gfx-rs/gfx/milestones{/number}","notifications_url":"https://api.github.com/repos/gfx-rs/gfx/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gfx-rs/gfx/labels{/name}","releases_url":"https://api.github.com/repos/gfx-rs/gfx/releases{/id}","deployments_url":"https://api.github.com/repos/gfx-rs/gfx/deployments","created_at":"2013-10-25T00:35:35Z","updated_at":"2016-09-05T23:42:28Z","pushed_at":"2016-09-05T22:26:40Z","git_url":"git://github.com/gfx-rs/gfx.git","ssh_url":"git@github.com:gfx-rs/gfx.git","clone_url":"https://github.com/gfx-rs/gfx.git","svn_url":"https://github.com/gfx-rs/gfx","homepage":"http://gfx-rs.github.io/","size":32073,"stargazers_count":664,"watchers_count":664,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":116,"mirror_url":null,"open_issues_count":110,"forks":116,"open_issues":110,"watchers":664,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037"},"html":{"href":"https://github.com/gfx-rs/gfx/pull/1037"},"issue":{"href":"https://api.github.com/repos/gfx-rs/gfx/issues/1037"},"comments":{"href":"https://api.github.com/repos/gfx-rs/gfx/issues/1037/comments"},"review_comments":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037/comments"},"review_comment":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/gfx-rs/gfx/pulls/1037/commits"},"statuses":{"href":"https://api.github.com/repos/gfx-rs/gfx/statuses/7fa00bac9aff93d98d590493f2ee83c7c3b05fb2"}}}}
{"actor":{"display_login":"kvark"}}